编辑 | blame | 历史 | 原始文档

文件上传规则

核心原则(AI 必须严格遵守)

所有文件上传必须走 yudao-module-system 模块的 Storage API + Attachment 中间表机制。

禁止在任何业务模块自行设计文件上传方案,包括但不限于:添加 file_url 列、新增 upload 接口、注入 FileApi。

文件与业务的关联方式

文件与业务记录的关联**只能通过 system_storage_attachment 中间表**,不允许在业务表中添加 file_urlfile_urlsattachment_url 等字符串字段存储文件地址。

关联流程:
1. 前端调用 POST /system/storage-blob/upload 上传文件 → 获得 blobId
2. 前端调用 POST /system/storage-attachment/bind 绑定文件到业务记录(传入 recordType + recordId + blobItems
3. 前端调用 GET /system/storage-attachment/list 查询附件
4. 前端调用 DELETE /system/storage-attachment/delete 删除附件

正确接口(system 模块)

方法 路径 说明
POST /system/storage-blob/upload 上传文件(files 参数,multipart)
POST /system/storage-blob/public-upload 公共文件上传(永久有效)
GET /system/storage-blob/preview/{fileName} 文件预览
GET /system/storage-blob/download/{fileName} 文件下载
GET /system/storage-attachment/list 查询附件列表
POST /system/storage-attachment/bind 绑定附件到业务记录
DELETE /system/storage-attachment/delete 批量删除附件

禁止行为(AI 严禁执行以下操作)

数据库层面

  • ❌ 禁止在业务表添加 file_urlfile_urlsattachment_url 等文件地址列
  • ❌ 禁止在业务表添加任何用于存储文件信息的 JSON 列

Java 后端层面

  • ❌ 禁止在 DO 类添加 fileUrlfileUrlsattachmentUrl 等字段
  • ❌ 禁止在 SaveReqVO / RespVO 添加文件地址字段
  • ❌ 禁止在 MES/CRM/ERP/HRM 等业务模块新增 @PostMapping("/upload") 接口
  • ❌ 禁止在 Controller 中使用 MultipartFile 参数(Excel 导入除外)
  • ❌ 禁止注入或调用 cn.iocoder.yudao.module.infra.api.file.FileApi

前端层面

  • ❌ 禁止调用 /infra/file/upload/infra/file/presigned-url
  • ❌ 禁止调用旧版 src/api/infra/file/index.ts 中的 uploadFile() 函数

常见 AI 幻觉模式(必须识别并拒绝)

以下是 AI 容易幻觉生成的设计模式,遇到类似需求时直接拒绝:

  1. "加个 fileUrl 字段就行" → 错误,必须用 attachment 中间表
  2. "参考其它模块的 fileUrl 字段" → 错误,其它模块的 fileUrl 也应被删除
  3. "在 Controller 加个 upload 接口" → 错误,统一走 system 模块
  4. "用 FileApi 上传文件" → 错误,FileApi 是 infra 模块的旧接口
  5. "在表单保存接口加 MultipartFile 参数" → 错误,上传和保存分离

正确示例

前端调用

import { uploadFile, bindAttachments, listAttachments } from '#/api/system/storage';

// 1. 上传文件
const blobs = await uploadFile([file]);
const blobId = blobs[0].id;

// 2. 保存业务记录后,绑定附件
await bindAttachments({
  application: 'file',
  recordType: 'erp_purchase_order',
  recordId: savedRecord.id,
  blobItems: [{ blobId }],
});

// 3. 查询附件
const attachments = await listAttachments({
  recordType: 'erp_purchase_order',
  recordId: savedRecord.id,
});

recordType 命名规范

格式:{模块前缀}_{业务表名}

模块 recordType
ERP 采购订单 erp_purchase_order
ERP 采购申请 erp_purchase_request
ERP 销售订单 erp_sale_order
ERP 收款单 erp_finance_receipt
ERP 付款单 erp_finance_payment
HRM 请假 hrm_leave_application
HRM 离职 hrm_resignation_application
HRM 调动 hrm_transfer_application
MES 采购订单 mes_purchase_order
MES 工单 mes_pro_work_order
CRM 客户 crm_customer

AI 自查清单

在实现任何文件上传相关需求前,逐项确认:

  • [ ] 是否使用了 /system/storage-blob/upload 上传?
  • [ ] 是否使用了 /system/storage-attachment/bind 关联?
  • [ ] 是否没有在业务表中添加文件地址列?
  • [ ] 是否没有在 DO/VO 中添加文件地址字段?
  • [ ] 是否没有创建新的 upload Controller 接口?
  • [ ] 是否没有使用 infra 模块的 FileApi?

以上 6 项全部为"是"才可继续。

为什么

  • 存储配置(本地/S3)在 system 模块统一管理
  • 附件绑定机制(storage-attachment)提供 recordType + recordId 的标准关联方式,支持多文件、用途分类
  • infra 模块的 /infra/file/* 是旧版接口,存在文件与业务记录无法关联的问题
  • 业务表存储 file_url 字符串无法支持多文件,且文件与业务记录之间缺乏标准化的关联管理