Files
AIclinicalresearch/docs/01-平台基础层/02-存储服务/OSS集成开发记录-2026-01-22.md
HaHafeng 2481b786d8 deploy: Complete 0126-27 deployment - database upgrade, services update, code recovery
Major Changes:
- Database: Install pg_bigm/pgvector plugins, create test database
- Python service: v1.0 -> v1.1, add pymupdf4llm/openpyxl/pypandoc
- Node.js backend: v1.3 -> v1.7, fix pino-pretty and ES Module imports
- Frontend: v1.2 -> v1.3, skip TypeScript check for deployment
- Code recovery: Restore empty files from local backup

Technical Fixes:
- Fix pino-pretty error in production (conditional loading)
- Fix ES Module import paths (add .js extensions)
- Fix OSSAdapter TypeScript errors
- Update Prisma Schema (63 models, 16 schemas)
- Update environment variables (DATABASE_URL, EXTRACTION_SERVICE_URL, OSS)
- Remove deprecated variables (REDIS_URL, DIFY_API_URL, DIFY_API_KEY)

Documentation:
- Create 0126 deployment folder with 8 documents
- Update database development standards v2.0
- Update SAE deployment status records

Deployment Status:
- PostgreSQL: ai_clinical_research_test with plugins
- Python: v1.1 @ 172.17.173.84:8000
- Backend: v1.7 @ 172.17.173.89:3001
- Frontend: v1.3 @ 172.17.173.90:80

Tested: All services running successfully on SAE
2026-01-27 08:13:27 +08:00

201 lines
5.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# OSS 集成开发记录
> 日期2026-01-22
> 版本v1.0
> 状态MVP 阶段完成
---
## 📋 开发目标
将阿里云 OSS 集成到平台中,替代本地文件存储,为 PKB个人知识库等业务模块提供可靠的云端文件持久化能力。
---
## ✅ 完成的工作
### 1. 基础设施层
#### 1.1 OSS Bucket 创建
| Bucket 名称 | 用途 | 权限 | 加密 |
|-------------|------|------|------|
| `ai-clinical-data` | 生产环境数据存储 | 私有 | SSE-OSS |
| `ai-clinical-data-dev` | 开发环境数据存储 | 私有 | 无 |
| `ai-clinical-static` | 生产环境静态资源 | 公共读 | 无 |
| `ai-clinical-static-dev` | 开发环境静态资源 | 公共读 | 无 |
#### 1.2 RAM 账号配置
- 创建专用 RAM 用户:`aiclinical-oss`
- 配置 AccessKey ID/Secret
- 授权 OSS 操作权限
### 2. 后端存储适配器
#### 2.1 架构设计
```
StorageAdapter (接口)
├── OSSAdapter (阿里云 OSS 实现)
└── LocalAdapter (本地文件系统实现)
StorageFactory (工厂类)
└── getInstance() 根据 STORAGE_TYPE 返回对应适配器
```
#### 2.2 核心文件
| 文件 | 说明 |
|------|------|
| `src/common/storage/StorageAdapter.ts` | 存储适配器接口定义 |
| `src/common/storage/OSSAdapter.ts` | OSS 实现上传、下载、删除、签名URL |
| `src/common/storage/LocalAdapter.ts` | 本地存储实现 |
| `src/common/storage/StorageFactory.ts` | 工厂类,根据环境变量创建实例 |
| `src/common/storage/index.ts` | 统一导出 |
#### 2.3 关键功能
- **上传文件**`storage.upload(key, buffer)`
- **下载文件**`storage.download(key)`
- **删除文件**`storage.delete(key)`
- **获取签名URL**`storage.getSignedUrl(key, expires, originalFilename)`
- **检查文件存在**`storage.exists(key)`
#### 2.4 签名URL与原始文件名
通过 `Content-Disposition` 响应头,让浏览器下载时恢复原始文件名:
```typescript
getSignedUrl(key: string, expires: number = 900, originalFilename?: string): string {
const options: OSS.SignatureUrlOptions = { expires };
if (originalFilename) {
options.response = {
'content-disposition': `attachment; filename="${encodeURIComponent(originalFilename)}"`
};
}
return this.client.signatureUrl(key, options);
}
```
### 3. PKB 模块集成
#### 3.1 目录结构规范
```
tenants/{tenantId}/users/{userId}/pkb/{kbId}/{uuid}.{ext}
```
示例:
```
tenants/yizhengxun/users/user-001/pkb/kb-001/9f206cc1c1ac4478.pdf
```
#### 3.2 代码修改
**documentController.ts**
- 新增 `generatePkbStorageKey()` 函数生成存储路径
- 上传流程:先上传到 OSS再调用 documentService
**documentService.ts**
- `uploadDocument()` 接收 `storageKey` 参数并存储
- `deleteDocument()` 删除 OSS 文件
#### 3.3 数据库字段重命名
| 原字段名 | 新字段名 | 说明 |
|----------|----------|------|
| `difyDocumentId` | `storageKey` | 存储 OSS 路径(数据库列名保持 `dify_document_id` 以避免迁移) |
### 4. 环境变量配置
```bash
# 存储类型oss 或 local
STORAGE_TYPE=oss
# OSS 配置
OSS_REGION=oss-cn-beijing
OSS_BUCKET=ai-clinical-data-dev
OSS_BUCKET_STATIC=ai-clinical-static-dev
OSS_ACCESS_KEY_ID=LTAI5tBHkL39GjdLfcr77Y3f
OSS_ACCESS_KEY_SECRET=********
OSS_INTERNAL=false # 本地开发用公网,生产用内网
```
### 5. 文档产出
| 文档 | 路径 |
|------|------|
| MVP 实施方案 | `docs/01-平台基础层/02-存储服务/OSS存储实施方案-MVP版.md` |
| 开发规范 | `docs/04-开发规范/11-OSS存储开发规范.md` |
| 账号配置信息 | `docs/01-平台基础层/02-存储服务/OSS账号与配置信息.md` |
---
## 🧪 测试结果
### OSS 适配器测试
```
✅ 上传成功
✅ 文件存在检查
✅ 下载成功(内容匹配)
✅ 签名URL生成含原始文件名
✅ 删除成功
```
### PKB 文档上传测试
```
✅ 文件上传到 OSS
✅ 数据库记录 storageKey
⚠️ 删除文档时遇到 pg-boss 队列冲突(与 OSS 无关)
```
---
## 🔧 待解决问题
| 问题 | 优先级 | 说明 |
|------|--------|------|
| pg-boss 队列重复初始化 | 高 | 导致服务启动报错 |
| 删除文档功能验证 | 中 | 需解决 pg-boss 后继续测试 |
| 前端文件预览/下载 | 中 | 需实现签名URL获取接口 |
| Tool C / RVW / ASL 集成 | 低 | 按实施方案逐步推进 |
---
## 📊 技术决策记录
### 决策 1文件命名使用 UUID
- **原因**:防止文件名冲突、避免特殊字符问题、增加安全性
- **方案**:上传时生成 UUID 作为 OSS Key原始文件名存数据库
### 决策 2保留 local 存储模式
- **原因**:支持医疗机构私有化部署(数据不出内网)
- **方案**:通过 `STORAGE_TYPE` 环境变量切换
### 决策 3复用 difyDocumentId 字段
- **原因**Dify 已移除,该字段可复用存储 OSS 路径
- **方案**Prisma 字段重命名为 `storageKey``@map` 保持原列名
### 决策 4文件大小限制 30MB
- **原因**:平衡用户体验和服务器内存安全
- **方案**30MB 以下用 `toBuffer()`,超大文件考虑流式处理
---
## 📅 后续计划
1. **Phase 2.1**:完成 PKB 删除功能验证
2. **Phase 2.2**:实现前端文件预览/下载签名URL
3. **Phase 3**:集成 Tool C、RVW、ASL 模块
4. **Phase 4**:生产环境部署与内网 Endpoint 配置
---
## 👥 参与人员
- 开发AI 助手 + 用户
- 审核:用户