# 文件接口 **本文引用的文件** - [FileController.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/controller/FileController.java) - [FileService.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/service/FileService.java) - [FileStorageProperties.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/config/FileStorageProperties.java) - [application.yaml](file://fms-api/src/main/resources/application.yaml) - [fileService.js](file://fms-vue/src/services/fileService.js) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考虑](#性能考虑) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本文件面向FMS系统的“文件接口”,提供统一的RESTful API,用于文件的上传、下载(预览)、删除与配置查询。系统支持两种存储模式:本地磁盘与阿里云OSS(通过g3oss服务)。前端会根据后端返回的存储类型自动选择上传路径,并在OSS模式下实现直传与凭证缓存,减少服务端压力。 ## 项目结构 - 控制器层:暴露 /api/file/* 端点,负责接收请求、参数校验与响应封装。 - 服务层:封装本地/ OSS 上传、记录持久化、删除等核心逻辑。 - 配置层:集中管理存储类型、本地存储目录、URL前缀、OSS地址等。 - 前端服务:根据后端配置动态切换上传策略,封装批量上传、预览链接生成、删除等操作。 ```mermaid graph TB Client["前端应用"] --> API["/api/file/* 控制器"] API --> Svc["FileService 服务"] Svc --> Local["本地文件系统"] Svc --> DB["数据库 bf_files"] Svc --> G3OSS["g3oss 服务(阿里云OSS代理)"] ``` 图表来源 - [FileController.java:28-112](file://fms-api/src/main/java/cn/g3soft/fmsapi/controller/FileController.java#L28-L112) - [FileService.java:51-266](file://fms-api/src/main/java/cn/g3soft/fmsapi/service/FileService.java#L51-L266) - [application.yaml:27-33](file://fms-api/src/main/resources/application.yaml#L27-L33) 章节来源 - [FileController.java:28-112](file://fms-api/src/main/java/cn/g3soft/fmsapi/controller/FileController.java#L28-L112) - [application.yaml:1-34](file://fms-api/src/main/resources/application.yaml#L1-L34) ## 核心组件 - FileController:定义文件相关API端点,包括配置查询、上传、凭证获取、保存记录、删除、静态资源访问。 - FileService:实现本地/ OSS 上传流程、DB记录写入、删除逻辑(含本地与OSS),以及OSS凭证转发。 - FileStorageProperties:绑定 application.yaml 中 fms.file.* 配置项,控制存储行为。 - fileService.js(前端):封装上传策略选择、批量上传、OSS直传、凭证缓存、预览链接生成与删除调用。 章节来源 - [FileController.java:28-112](file://fms-api/src/main/java/cn/g3soft/fmsapi/controller/FileController.java#L28-L112) - [FileService.java:51-266](file://fms-api/src/main/java/cn/g3soft/fmsapi/service/FileService.java#L51-L266) - [FileStorageProperties.java:1-69](file://fms-api/src/main/java/cn/g3soft/fmsapi/config/FileStorageProperties.java#L1-L69) - [fileService.js:1-149](file://fms-vue/src/services/fileService.js#L1-L149) ## 架构总览 系统采用前后端分离架构,后端统一暴露文件接口,前端根据后端返回的存储类型自动选择上传方式。本地模式由后端直接落盘并写库;OSS模式由前端直传到g3oss,再回调后端保存记录。 ```mermaid sequenceDiagram participant FE as "前端" participant CTRL as "FileController" participant SVC as "FileService" participant FS as "本地文件系统" participant DB as "数据库" participant G3 as "g3oss(OSS)" Note over FE,CTRL : 本地上传流程 FE->>CTRL : POST /api/file/upload (files, father, moduleId, cateId) CTRL->>SVC : localUpload(files, ...) loop 逐个文件 SVC->>FS : 写入磁盘(按 orgId/yyyy/MM/dd/) SVC->>DB : INSERT bf_files end SVC-->>CTRL : 文件元数据列表 CTRL-->>FE : 成功响应 Note over FE,G3 : OSS直传流程 FE->>CTRL : POST /api/file/upload-credential CTRL->>SVC : ossCredential() SVC->>G3 : 获取上传凭证 G3-->>SVC : 凭证 SVC-->>CTRL : 凭证 CTRL-->>FE : 凭证 FE->>G3 : XHR 直传文件 FE->>CTRL : POST /api/file/save-record (记录) CTRL->>SVC : saveRecord(...) SVC->>DB : INSERT bf_files SVC-->>CTRL : 结果 CTRL-->>FE : 成功响应 ``` 图表来源 - [FileController.java:41-87](file://fms-api/src/main/java/cn/g3soft/fmsapi/controller/FileController.java#L41-L87) - [FileService.java:51-118](file://fms-api/src/main/java/cn/g3soft/fmsapi/service/FileService.java#L51-L118) - [FileService.java:162-179](file://fms-api/src/main/java/cn/g3soft/fmsapi/service/FileService.java#L162-L179) - [fileService.js:25-85](file://fms-vue/src/services/fileService.js#L25-L85) ## 详细组件分析 ### RESTful API 端点清单 - 查询存储配置 - 方法:POST - 路径:/api/file/config - 说明:返回当前存储类型 storageType(local 或 aliyun-oss) - 请求体:无 - 响应:包含 storageType 的对象 - 本地上传(多文件) - 方法:POST - 路径:/api/file/upload - 说明:使用 FormData,key 为 files;同时传入 father、moduleId、可选 cateId - 请求体:multipart/form-data - 响应:文件元数据列表(包含 subid、文件名、大小、扩展名、映射路径、模块ID、分类ID等) - 获取OSS上传凭证 - 方法:POST - 路径:/api/file/upload-credential - 说明:后端转发到 g3oss 获取凭证,bucket=机构码 - 请求体:无 - 响应:包含 accessid、policy、signature、dir、host 等 - 保存文件记录(OSS直传后回调) - 方法:POST - 路径:/api/file/save-record - 说明:前端直传成功后回调,写入 bf_files - 请求体:包含 subid、father、mx_moduleid、mx_cate_id、mx_filename、mx_filesize、mx_fileext、mx_mapfilename - 响应:保存结果 - 删除文件 - 方法:POST - 路径:/api/file/delete - 说明:根据 subid 删除存储文件与数据库记录 - 请求体:{ subid } - 响应:成功空对象 - 本地文件访问(预览/下载) - 方法:GET - 路径:/api/file/static/{fileName} - 说明:读取本地磁盘文件并以流形式返回,设置 inline 内容处置头 - 路径参数:fileName(包含子目录:orgId/yyyy/MM/dd/文件名) - 响应:文件二进制流 章节来源 - [FileController.java:41-111](file://fms-api/src/main/java/cn/g3soft/fmsapi/controller/FileController.java#L41-L111) ### 数据模型与字段说明 - 文件记录表 bf_files(写入字段) - subid:文件唯一标识(雪花ID) - father:父级ID(可为空) - mx_filename:原始文件名 - mx_filesize:文件大小(字节) - mx_fileext:扩展名(小写) - mx_mapfilename:映射路径或URL(本地为相对路径,OSS为完整URL) - mx_moduleid:所属模块ID(可为空) - mx_cate_id:分类ID(可为空) - mx_xh:排序号(默认0) - mx_sh:审核状态(默认0) - mx_inputuser_id:录入人ID - mx_inputdatetime:录入时间 章节来源 - [FileService.java:120-148](file://fms-api/src/main/java/cn/g3soft/fmsapi/service/FileService.java#L120-L148) ### 存储配置与扩展 - 配置文件位置:application.yaml 中 fms.file.* - 关键配置项 - storage-type:存储类型,可选 local 或 aliyun-oss - local.storage-dir:本地存储根目录 - local.url-prefix:本地文件访问URL前缀 - oss.g3oss-url:g3oss服务地址(用于获取凭证与删除) - 扩展方式 - 新增存储类型:在 FileStorageProperties 增加对应配置类,并在 FileService 中扩展处理分支 - 自定义URL生成规则:调整 local.url-prefix 或在服务层拼接 - 鉴权与限流:可在控制器层增加拦截器或网关策略 章节来源 - [application.yaml:27-33](file://fms-api/src/main/resources/application.yaml#L27-L33) - [FileStorageProperties.java:1-69](file://fms-api/src/main/java/cn/g3soft/fmsapi/config/FileStorageProperties.java#L1-L69) - [FileService.java:183-246](file://fms-api/src/main/java/cn/g3soft/fmsapi/service/FileService.java#L183-L246) ### 权限与安全 - 路径穿越防护:本地文件访问时对解析路径进行规范化校验,确保不越出存储根目录 - 上下文信息:文件写入时从 OrgContext 获取当前机构与用户ID,用于归属与审计 - 凭证安全:OSS凭证由后端转发获取,前端仅持有临时凭证,避免直接暴露密钥 章节来源 - [FileController.java:92-111](file://fms-api/src/main/java/cn/g3soft/fmsapi/controller/FileController.java#L92-L111) - [FileService.java:120-148](file://fms-api/src/main/java/cn/g3soft/fmsapi/service/FileService.java#L120-L148) - [FileService.java:162-179](file://fms-api/src/main/java/cn/g3soft/fmsapi/service/FileService.java#L162-L179) ### 前端集成要点 - 初始化存储模式:调用 /api/file/config 获取 storageType - 批量上传: - 本地模式:构造 FormData,files key 追加多个文件,一次性提交 - OSS模式:先获取凭证,然后逐个XHR直传到g3oss,最后回调 /api/file/save-record 写入记录 - 预览链接:直接使用文件记录的 mx_mapfilename - 删除文件:调用 /api/file/delete,传入 subid - 凭证缓存:前端对OSS凭证进行缓存,避免频繁请求 章节来源 - [fileService.js:1-149](file://fms-vue/src/services/fileService.js#L1-L149) ## 依赖关系分析 - 控制器依赖服务层,服务层依赖配置与数据库工具,必要时调用外部g3oss服务 - 前端依赖后端配置以决定上传策略,并在OSS模式下直传至g3oss ```mermaid classDiagram class FileController { +config() +upload() +uploadCredential() +saveRecord() +delete() +serveFile() } class FileService { +localUpload() +saveRecord() +ossCredential() +delete() } class FileStorageProperties { +storageType +local +oss } class DbUtils class OrgContext FileController --> FileService : "调用" FileService --> FileStorageProperties : "读取配置" FileService --> DbUtils : "读写数据库" FileService --> OrgContext : "获取上下文" ``` 图表来源 - [FileController.java:28-112](file://fms-api/src/main/java/cn/g3soft/fmsapi/controller/FileController.java#L28-L112) - [FileService.java:34-266](file://fms-api/src/main/java/cn/g3soft/fmsapi/service/FileService.java#L34-L266) - [FileStorageProperties.java:1-69](file://fms-api/src/main/java/cn/g3soft/fmsapi/config/FileStorageProperties.java#L1-L69) 章节来源 - [FileController.java:28-112](file://fms-api/src/main/java/cn/g3soft/fmsapi/controller/FileController.java#L28-L112) - [FileService.java:34-266](file://fms-api/src/main/java/cn/g3soft/fmsapi/service/FileService.java#L34-L266) ## 性能考虑 - 本地上传:后端逐个写盘并插入记录,适合中小文件;大文件建议启用OSS直传以降低带宽与内存占用 - OSS直传:前端直传g3oss,减少后端IO与网络开销;凭证缓存减少重复请求 - 数据库连接:使用连接池配置,合理设置最大活动连接数与等待时间 - 并发与限流:可根据业务场景在后端或网关层增加限流策略 [本节为通用指导,不直接分析具体文件] ## 故障排查指南 - 本地文件访问404:检查路径是否规范且未发生穿越;确认存储目录与URL前缀配置正确 - OSS凭证失败:检查 g3oss-url 可达性与返回状态码;确认机构上下文有效 - 删除失败:确认 subid 存在;检查本地文件是否存在;OSS删除需确认 objectName 提取正确 - 上传记录不一致:OSS直传成功后务必回调 save-record;若失败需重试或补偿 章节来源 - [FileController.java:92-111](file://fms-api/src/main/java/cn/g3soft/fmsapi/controller/FileController.java#L92-L111) - [FileService.java:162-179](file://fms-api/src/main/java/cn/g3soft/fmsapi/service/FileService.java#L162-L179) - [FileService.java:183-246](file://fms-api/src/main/java/cn/g3soft/fmsapi/service/FileService.java#L183-L246) ## 结论 FMS文件接口提供了统一的文件管理能力,支持本地与OSS双模式,具备基本的安全防护与上下文感知能力。前端通过配置驱动自动选择上传策略,兼顾易用性与性能。后续可按需扩展新的存储后端或增强权限控制。 [本节为总结性内容,不直接分析具体文件] ## 附录 ### 典型调用示例(步骤说明) - 多文件本地上传 - 前端构造 FormData,append files、father、moduleId、cateId - 调用 POST /api/file/upload - 返回文件元数据列表,可用于展示与预览 - OSS直传与进度跟踪 - 调用 POST /api/file/upload-credential 获取凭证 - 使用 XHR 逐个直传到 g3oss,可监听 loadprogress 事件实现进度条 - 直传成功后调用 POST /api/file/save-record 写入记录 - 预览链接生成 - 直接使用文件记录的 mx_mapfilename - 删除文件 - 调用 POST /api/file/delete,传入 subid 章节来源 - [fileService.js:25-85](file://fms-vue/src/services/fileService.js#L25-L85) - [FileController.java:41-87](file://fms-api/src/main/java/cn/g3soft/fmsapi/controller/FileController.java#L41-L87) ### 流程图:本地文件访问 ```mermaid flowchart TD Start(["进入 serveFile"]) --> Resolve["解析 fileName 并规范化路径"] Resolve --> Check{"路径合法且在存储根目录下?"} Check --> |否| NotFound["返回 404"] Check --> |是| Serve["设置响应头并输出文件流"] Serve --> End(["结束"]) ``` 图表来源 - [FileController.java:92-111](file://fms-api/src/main/java/cn/g3soft/fmsapi/controller/FileController.java#L92-L111)