# 文件API **本文引用的文件** - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApi.java](file://crm-file/src/main/java/com/crm/file/api/FileApi.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) - [IFileInfoService.java](file://crm-file/src/main/java/com/crm/file/service/IFileInfoService.java) - [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) - [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java) - [SchedulingConfig.java](file://crm-file/src/main/java/com/crm/file/config/SchedulingConfig.java) - [OrphanChunkCleanupTask.java](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java) - [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java) - [ThumbnailPlaceholderService.java](file://crm-file/src/main/java/com/crm/file/service/ThumbnailPlaceholderService.java) - [FileInfo.java](file://crm-file/src/main/java/com/crm/file/domain/entity/FileInfo.java) - [FileInfoMapper.java](file://crm-file/src/main/java/com/crm/file/mapper/FileInfoMapper.java) - [MultipartInitDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/MultipartInitDTO.java) - [UploadSession.java](file://crm-file/src/main/java/com/crm/file/domain/dto/UploadSession.java) - [FileDownloadDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/FileDownloadDTO.java) - [FileInfoDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/FileInfoDTO.java) - [ThumbnailDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/ThumbnailDTO.java) - [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java) ## 更新摘要 **变更内容** - 新增缩略图API端点 `/api/file/thumbnail`,支持二进制图片数据和JSON信封响应 - 增强FileApiImpl中的缩略图生命周期管理,实现状态跟踪(PENDING, READY, FAILED, UNSUPPORTED) - 添加同步回退机制,在异步任务未完成时提供即时响应 - 完善缩略图生成、缓存策略和错误处理流程 ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考虑](#性能考虑) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录:接口清单与规范](#附录接口清单与规范) ## 简介 本文件管理模块提供统一的文件上传、下载、预览、删除等能力,支持分片上传、断点续传与并发上传;集成 MinIO 对象存储与 KkFileView 在线预览服务;提供缩略图生成、临时访问链接、权限控制与批量操作。文档面向开发者与集成方,覆盖 HTTP 接口、数据模型、存储策略、安全校验、错误处理与优化建议。 **更新** 新增缩略图API端点,支持智能状态管理和同步回退机制,提供更健壮的缩略图获取体验。 ## 项目结构 文件模块位于 crm-file 子模块,采用分层组织: - controller:HTTP 接口层 - api:对外 API 抽象 - service:业务逻辑与外部服务客户端(MinIO、KkFileView) - domain:实体、DTO、枚举与常量 - config:配置类(MinIO、调度任务、文件属性) - task:定时清理任务(分片残留清理、缩略图生成) - mapper:数据库映射(文件元信息) ```mermaid graph TB subgraph "crm-file" C["controller.FileController"] --> A["api.FileApi"] A --> S1["service.impl.FileApiImpl"] S1 --> S2["service.IFileInfoService"] S2 --> S3["service.impl.FileInfoServiceImpl"] S1 --> M["config.MinioConfig"] S1 --> P["config.FileProperties"] S1 --> K["service.KkFileViewClient"] S1 --> TGT["task.ThumbnailGenerationTask"] S1 --> TPS["service.ThumbnailPlaceholderService"] S3 --> E["domain.entity.FileInfo"] S3 --> MAP["mapper.FileInfoMapper"] T["task.OrphanChunkCleanupTask"] --> M T --> S2 end ``` **图表来源** - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApi.java](file://crm-file/src/main/java/com/crm/file/api/FileApi.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [IFileInfoService.java](file://crm-file/src/main/java/com/crm/file/service/IFileInfoService.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) - [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java) - [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java) - [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java) - [ThumbnailPlaceholderService.java](file://crm-file/src/main/java/com/crm/file/service/ThumbnailPlaceholderService.java) - [FileInfo.java](file://crm-file/src/main/java/com/crm/file/domain/entity/FileInfo.java) - [FileInfoMapper.java](file://crm-file/src/main/java/com/crm/file/mapper/FileInfoMapper.java) - [OrphanChunkCleanupTask.java](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java) ## 核心组件 - FileController:暴露 REST 接口,统一接收请求并委派给 FileApi。 - FileApi / FileApiImpl:定义并实现文件上传、下载、预览、删除、分片、续传、缩略图等核心流程。 - IFileInfoService / FileInfoServiceImpl:文件元数据持久化、查询、状态管理与事务边界。 - MinioConfig:MinIO 客户端配置与桶策略。 - FileProperties:文件大小限制、允许类型、路径规则等配置项。 - KkFileViewClient:调用第三方预览服务,生成预览链接或缩略图。 - ThumbnailGenerationTask:异步缩略图生成任务,支持分布式锁和重试机制。 - ThumbnailPlaceholderService:动态生成文件类型占位图。 - OrphanChunkCleanupTask:定时清理未完成的分片文件,释放空间。 - FileInfo 实体与 Mapper:文件元信息表结构与数据访问。 **更新** 新增缩略图相关组件,提供完整的缩略图生命周期管理能力。 ## 架构总览 整体采用"控制器-服务-存储/外部服务"的分层架构: - 控制器负责参数校验、鉴权与响应封装。 - 服务层编排上传、下载、预览、删除等业务流程,协调 MinIO 与 KkFileView。 - 配置层集中管理 MinIO、文件属性与调度任务。 - 数据层通过 MyBatis-Plus 维护文件元信息。 ```mermaid sequenceDiagram participant Client as "客户端" participant Controller as "FileController" participant Api as "FileApiImpl" participant Task as "ThumbnailGenerationTask" participant MinIO as "MinIO 存储" participant Preview as "KkFileView 预览服务" participant DB as "数据库(FileInfo)" Client->>Controller : "POST /api/file/upload/init" Controller->>Api : "初始化分片会话" Api->>DB : "创建上传会话/记录" Api-->>Controller : "返回会话ID/分片大小" Controller-->>Client : "会话信息" loop "分片上传" Client->>Controller : "POST /api/file/upload/chunk" Controller->>Api : "上传分片" Api->>MinIO : "PutObject(分片)" Api->>DB : "记录分片状态" Api-->>Controller : "分片上传结果" Controller-->>Client : "分片成功/失败" end Client->>Controller : "POST /api/file/upload/complete" Controller->>Api : "合并分片/完成上传" Api->>MinIO : "CompleteMultipartUpload" Api->>DB : "写入文件元信息" Api->>Task : "触发异步缩略图生成" Api-->>Controller : "文件信息" Controller-->>Client : "文件URL/预览链接" Client->>Controller : "GET /api/file/thumbnail/{id}" Controller->>Api : "获取缩略图" Api->>Task : "尝试同步生成" Task-->>Api : "生成结果" Api->>MinIO : "读取缩略图" Api-->>Controller : "缩略图数据" Controller-->>Client : "二进制图片流" ``` **图表来源** - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) - [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) - [FileInfo.java](file://crm-file/src/main/java/com/crm/file/domain/entity/FileInfo.java) ## 详细组件分析 ### 文件上传接口(普通上传) - 方法:POST - 路径:/api/file/upload - 请求体:multipart/form-data,字段 file(二进制文件) - 响应:文件基本信息(ID、名称、大小、URL、预览链接) - 校验:文件名白名单、大小限制、MIME 类型校验、重复检测 - 存储:MinIO 直传,按日期/用户维度组织桶路径 - 安全:鉴权拦截器校验登录态与权限 ```mermaid flowchart TD Start(["进入上传接口"]) --> Validate["校验请求参数与权限"] Validate --> CheckType{"文件类型允许?"} CheckType --> |否| ErrType["返回类型不允许错误"] CheckType --> |是| CheckSize{"文件大小合规?"} CheckSize --> |否| ErrSize["返回大小超限错误"] CheckSize --> |是| Upload["调用 MinIO 上传"] Upload --> SaveMeta["持久化文件元信息"] SaveMeta --> GenThumb["触发缩略图生成"] GenThumb --> Return["返回文件信息"] ErrType --> End(["结束"]) ErrSize --> End Return --> End ``` **图表来源** - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) **章节来源** - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) ### 分片上传(含断点续传与并发) - 初始化会话:POST /api/file/upload/init - 参数:fileName、fileSize、chunkSize、uploadId - 响应:uploadId、分片大小、已存在分片列表 - 上传分片:POST /api/file/upload/chunk - 参数:uploadId、chunkIndex、chunkData - 行为:幂等上传,支持并发;记录分片状态 - 完成上传:POST /api/file/upload/complete - 参数:uploadId、fileName、fileSize、checksum - 行为:合并分片、落盘、写元信息、生成访问链接 - 断点续传:基于 uploadId 与分片索引去重,未上传分片可重试 - 并发上传:客户端并行上传分片,服务端保证幂等与顺序无关 ```mermaid sequenceDiagram participant C as "客户端" participant Ctrl as "FileController" participant Api as "FileApiImpl" participant MinIO as "MinIO" participant DB as "FileInfoService" C->>Ctrl : "init(uploadId, fileName, fileSize, chunkSize)" Ctrl->>Api : "初始化会话" Api->>DB : "创建会话/查询已上传分片" Api-->>Ctrl : "返回分片策略" Ctrl-->>C : "分片策略" par "并发上传分片" C->>Ctrl : "chunk(uploadId, index, data)" Ctrl->>Api : "上传分片" Api->>MinIO : "分片PutObject" Api->>DB : "记录分片状态" Api-->>Ctrl : "分片成功" Ctrl-->>C : "分片成功" end C->>Ctrl : "complete(uploadId, checksum)" Ctrl->>Api : "合并分片" Api->>MinIO : "CompleteMultipartUpload" Api->>DB : "写入文件元信息" Api-->>Ctrl : "文件信息" Ctrl-->>C : "文件URL/预览链接" ``` **图表来源** - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [MultipartInitDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/MultipartInitDTO.java) - [UploadSession.java](file://crm-file/src/main/java/com/crm/file/domain/dto/UploadSession.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) **章节来源** - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [MultipartInitDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/MultipartInitDTO.java) - [UploadSession.java](file://crm-file/src/main/java/com/crm/file/domain/dto/UploadSession.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) ### 文件下载接口 - 方法:GET - 路径:/api/file/download/{id} - 参数:id(文件ID)、可选签名参数(如过期时间) - 响应:文件流(Content-Disposition 设置下载名) - 权限:需具备文件读取权限;支持私有桶访问(预签名 URL) - 缓存:浏览器缓存控制头由服务端设置 ```mermaid sequenceDiagram participant Client as "客户端" participant Controller as "FileController" participant Api as "FileApiImpl" participant MinIO as "MinIO" Client->>Controller : "GET /api/file/download/{id}" Controller->>Api : "校验权限/构建下载参数" Api->>MinIO : "GetObject(或预签名URL)" MinIO-->>Api : "文件流/URL" Api-->>Controller : "流/URL" Controller-->>Client : "文件流/重定向" ``` **图表来源** - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) **章节来源** - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) ### 文件预览接口 - 方法:GET - 路径:/api/file/preview/{id} - 功能:根据文件类型调用 KkFileView 生成预览链接或直接返回预览页面 - 参数:id(文件ID)、可选格式参数(pdf/html/img) - 响应:预览页面或跳转链接 ```mermaid sequenceDiagram participant Client as "客户端" participant Controller as "FileController" participant Api as "FileApiImpl" participant Preview as "KkFileViewClient" Client->>Controller : "GET /api/file/preview/{id}" Controller->>Api : "解析文件类型/构造预览参数" Api->>Preview : "生成预览URL" Preview-->>Api : "预览URL" Api-->>Controller : "预览URL" Controller-->>Client : "跳转/嵌入预览" ``` **图表来源** - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java) **章节来源** - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java) ### 文件删除接口 - 方法:DELETE - 路径:/api/file/delete/{id} - 权限:仅文件所有者或管理员可删除 - 行为:删除 MinIO 对象与数据库元信息;软删除标记可选 ```mermaid flowchart TD Start(["进入删除接口"]) --> Auth["鉴权与所有权校验"] Auth --> Exists{"文件存在?"} Exists --> |否| NotFound["返回资源不存在"] Exists --> |是| DeleteMinIO["删除 MinIO 对象"] DeleteMinIO --> DeleteDB["删除/标记文件元信息"] DeleteDB --> Ok["返回删除成功"] NotFound --> End(["结束"]) Ok --> End ``` **图表来源** - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) **章节来源** - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) ### 缩略图API端点(新增) - 方法:GET - 路径:/api/file/thumbnail/{id} - 功能:获取文件缩略图,支持智能状态管理和同步回退 - 参数:id(文件ID) - 响应:二进制图片数据(image/jpeg)或占位图(image/png) - 状态码:200(正常)、202(缩略图生成中,稍后重试) **更新** 新增缩略图API端点,提供 sophisticated 的响应处理和状态管理。 ```mermaid sequenceDiagram participant Client as "客户端" participant Controller as "FileController" participant Api as "FileApiImpl" participant Task as "ThumbnailGenerationTask" participant MinIO as "MinIO" Client->>Controller : "GET /api/file/thumbnail/{id}" Controller->>Api : "获取缩略图" Api->>Api : "检查缩略图状态" alt 状态为READY Api->>MinIO : "读取缩略图" MinIO-->>Api : "缩略图数据" Api-->>Controller : "缩略图数据" else 状态为PENDING Api->>Task : "尝试同步生成" Task-->>Api : "生成结果" Api->>MinIO : "读取缩略图" MinIO-->>Api : "缩略图数据" Api-->>Controller : "缩略图数据" else 其他状态 Api->>Api : "生成占位图" Api-->>Controller : "占位图数据" end Controller-->>Client : "二进制图片流" ``` **图表来源** - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java) - [ThumbnailPlaceholderService.java](file://crm-file/src/main/java/com/crm/file/service/ThumbnailPlaceholderService.java) **章节来源** - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java) - [ThumbnailPlaceholderService.java](file://crm-file/src/main/java/com/crm/file/service/ThumbnailPlaceholderService.java) ### 缩略图生命周期管理(新增) - 状态机:PENDING → READY / FAILED / UNSUPPORTED - 初始状态:上传时根据文件类型判断(支持的类型设为PENDING,不支持的设为UNSUPPORTED) - 异步生成:上传完成后触发异步缩略图生成任务 - 同步回退:首次请求时若异步任务未完成,尝试同步生成 - 轮询等待:同步生成失败时轮询状态,超时返回202状态码 - 降级处理:生成失败或超时时返回占位图 ```mermaid stateDiagram-v2 [*] --> PENDING : 上传成功支持类型 [*] --> UNSUPPORTED : 上传成功不支持类型 PENDING --> READY : 缩略图生成成功 PENDING --> FAILED : 缩略图生成失败重试耗尽 PENDING --> PENDING : 缩略图生成失败继续重试 READY --> [*] FAILED --> [*] UNSUPPORTED --> [*] ``` **图表来源** - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java) - [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java) **章节来源** - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java) - [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java) ### 批量操作接口 - 批量删除:POST /api/file/batch/delete - 参数:ids(数组) - 行为:逐个校验权限后执行删除 - 批量下载:POST /api/file/batch/download - 参数:ids(数组) - 行为:打包为 ZIP 流返回(大文件建议分页或异步任务) ```mermaid sequenceDiagram participant Client as "客户端" participant Controller as "FileController" participant Api as "FileApiImpl" Client->>Controller : "POST /api/file/batch/delete {ids}" Controller->>Api : "遍历校验与删除" Api-->>Controller : "结果汇总" Controller-->>Client : "批量结果" ``` **图表来源** - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) **章节来源** - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) ### 临时链接生成 - 场景:私有桶访问、外链分享 - 接口:GET /api/file/presigned-url?fileId=xxx&expires=秒数 - 行为:生成 MinIO 预签名 URL,带过期时间与访问权限 - 安全:结合鉴权与访问控制策略 ```mermaid sequenceDiagram participant Client as "客户端" participant Controller as "FileController" participant Api as "FileApiImpl" participant MinIO as "MinIO" Client->>Controller : "GET /api/file/presigned-url" Controller->>Api : "校验权限/计算过期时间" Api->>MinIO : "GeneratePresignedUrl" MinIO-->>Api : "预签名URL" Api-->>Controller : "URL" Controller-->>Client : "临时链接" ``` **图表来源** - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) **章节来源** - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) ### 分片残留清理任务 - 任务:定时扫描未完成上传的会话与分片,清理无效数据 - 策略:超过保留时间的会话自动清理,避免磁盘膨胀 - 配置:调度周期与保留时长在配置中管理 ```mermaid flowchart TD Start(["定时任务启动"]) --> Scan["扫描未完成会话"] Scan --> Filter{"是否超期?"} Filter --> |否| Next["跳过"] Filter --> |是| Cleanup["清理分片与会话"] Cleanup --> Log["记录清理日志"] Log --> End(["结束"]) Next --> End ``` **图表来源** - [OrphanChunkCleanupTask.java](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java) - [SchedulingConfig.java](file://crm-file/src/main/java/com/crm/file/config/SchedulingConfig.java) **章节来源** - [OrphanChunkCleanupTask.java](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java) - [SchedulingConfig.java](file://crm-file/src/main/java/com/crm/file/config/SchedulingConfig.java) ## 依赖关系分析 - FileController 依赖 FileApi,解耦 HTTP 与业务逻辑。 - FileApiImpl 依赖 MinioConfig(MinIO 客户端)、FileProperties(配置)、KkFileViewClient(预览)。 - FileInfoServiceImpl 依赖 FileInfo 实体与 FileInfoMapper(MyBatis-Plus)。 - OrphanChunkCleanupTask 依赖 MinIO 与 FileInfoService 进行清理。 - **更新** FileApiImpl 新增对 ThumbnailGenerationTask 和 ThumbnailPlaceholderService 的依赖。 ```mermaid classDiagram class FileController { +upload() +download() +preview() +delete() +batchDelete() +presignedUrl() +thumbnail() } class FileApiImpl { +initMultipart() +uploadChunk() +completeMultipart() +download() +preview() +thumbnail() +delete() +presignedUrl() } class ThumbnailGenerationTask { +isSupported() +assignInitialStatus() +generate() +tryGenerateSync() } class ThumbnailPlaceholderService { +getPlaceholder() } class MinioConfig { +client +bucket } class FileProperties { +maxFileSize +allowedTypes +pathRules } class KkFileViewClient { +generatePreviewUrl() } class FileInfoServiceImpl { +save() +query() +updateStatus() } class FileInfo { +id +name +size +url +status +thumbnailStatus } class FileInfoMapper FileController --> FileApiImpl : "调用" FileApiImpl --> MinioConfig : "使用" FileApiImpl --> FileProperties : "读取配置" FileApiImpl --> KkFileViewClient : "调用预览" FileApiImpl --> FileInfoServiceImpl : "元数据操作" FileApiImpl --> ThumbnailGenerationTask : "缩略图生成" FileApiImpl --> ThumbnailPlaceholderService : "占位图生成" FileInfoServiceImpl --> FileInfo : "实体" FileInfoServiceImpl --> FileInfoMapper : "数据访问" ``` **图表来源** - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java) - [ThumbnailPlaceholderService.java](file://crm-file/src/main/java/com/crm/file/service/ThumbnailPlaceholderService.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) - [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java) - [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) - [FileInfo.java](file://crm-file/src/main/java/com/crm/file/domain/entity/FileInfo.java) - [FileInfoMapper.java](file://crm-file/src/main/java/com/crm/file/mapper/FileInfoMapper.java) **章节来源** - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java) - [ThumbnailPlaceholderService.java](file://crm-file/src/main/java/com/crm/file/service/ThumbnailPlaceholderService.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) - [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java) - [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) - [FileInfo.java](file://crm-file/src/main/java/com/crm/file/domain/entity/FileInfo.java) - [FileInfoMapper.java](file://crm-file/src/main/java/com/crm/file/mapper/FileInfoMapper.java) ## 性能考虑 - 分片上传:合理设置分片大小(建议 5~10MB),提升大文件上传稳定性与并发度。 - 并发上传:客户端并行上传分片,服务端幂等处理,避免重复写入。 - 流式下载:使用流式响应减少内存占用,支持 Range 断点续传。 - **更新** 缩略图:异步生成与缓存,命中缓存直接返回;同步回退机制避免阻塞。 - 预览服务:KkFileView 集群部署与缓存加速,避免单点瓶颈。 - 连接池:MinIO 客户端连接池与超时参数调优。 - 压缩与缓存:对静态资源启用 GZIP 与浏览器缓存。 - 限流与熔断:对上传/下载接口实施限流,异常时快速失败。 **更新** 缩略图性能优化包括异步生成、分布式锁、缓存策略和同步回退机制。 ## 故障排查指南 - 上传失败:检查文件类型与大小限制、网络超时、MinIO 连通性。 - 分片丢失:核对 uploadId 与分片索引,查看分片状态记录。 - 预览失败:确认 KkFileView 服务可用性与文件格式支持。 - 下载慢:检查带宽、MinIO 延迟、是否命中预签名 URL。 - 权限问题:校验登录态、角色与数据范围。 - 清理任务:查看调度配置与日志,确认清理阈值合理。 - **更新** 缩略图问题:检查缩略图状态、生成任务执行情况、Redis锁状态、MinIO缩略图存储。 **更新** 新增缩略图故障排查指南,包括状态检查、任务监控和缓存验证。 ## 结论 文件模块以清晰的分层架构与完善的流程设计,提供了稳定高效的文件管理能力。通过分片上传、断点续传、并发上传与预览集成,满足企业级场景需求。配合 MinIO 与权限控制,确保数据安全与访问可控。**更新** 新增的缩略图功能提供了完整的生命周期管理和智能状态处理,进一步提升了用户体验。建议在大规模使用时关注连接池、缓存与限流等性能优化点。 ## 附录:接口清单与规范 ### 接口清单 - 普通上传:POST /api/file/upload - 分片初始化:POST /api/file/upload/init - 分片上传:POST /api/file/upload/chunk - 分片完成:POST /api/file/upload/complete - 文件下载:GET /api/file/download/{id} - 文件预览:GET /api/file/preview/{id} - **更新** 缩略图:GET /api/file/thumbnail/{id} - 删除文件:DELETE /api/file/delete/{id} - 批量删除:POST /api/file/batch/delete - 批量下载:POST /api/file/batch/download - 临时链接:GET /api/file/presigned-url ### 请求参数与响应格式 - 上传参数:file(二进制)、fileName、fileSize、chunkSize、uploadId、chunkIndex、checksum - 下载参数:id、可选签名参数 - 预览参数:id、format(可选) - **更新** 缩略图参数:id(文件ID) - 删除参数:id、ids(批量) - 响应格式:统一 Result 包装,包含 code、message、data;缩略图接口例外返回二进制数据 ### 存储策略 - MinIO 桶命名:按业务域划分(如 file-prod、file-dev) - 路径规则:/tenant/user/date/originalName - **更新** 缩略图路径:/thumbnails/{fileId}.jpg - 分片路径:/chunks/{uploadId}/... ### 支持的文件格式与大小限制 - 允许类型:image/*、application/pdf、application/msword、application/vnd.openxmlformats-officedocument.*、text/* - 大小限制:默认 100MB,可通过配置调整 - 安全检查:MIME 类型校验、扩展名校验、内容扫描(可选) ### 安全校验规则 - 鉴权:JWT 登录态校验 - 权限:基于角色与数据范围的访问控制 - 输入校验:白名单类型、大小限制、文件名清洗 - 输出控制:下载与预览链接有效期控制 ### MinIO 存储配置 - 端点、AccessKey、SecretKey、Bucket、Region - 连接池大小、超时时间、重试次数 - 桶策略:读写权限、匿名访问开关 ### 文件访问权限控制 - 私有桶:通过预签名 URL 访问 - 公开桶:受限域名与 Referer 白名单 - 租户隔离:路径前缀区分租户 ### 临时链接生成 - 过期时间:秒级精度,默认 1 小时 - 权限继承:继承原文件的访问策略 - 防滥用:频率限制与 IP 白名单 ### 文件预览服务集成 - KkFileView 地址、超时、重试 - 支持的格式与渲染选项 - 缓存策略:本地缓存与 CDN 加速 ### 缩略图服务集成(新增) - **更新** 缩略图生成:异步任务 + 同步回退机制 - 状态管理:PENDING、READY、FAILED、UNSUPPORTED - 缓存策略:cacheable=true时设置max-age=86400,false时no-cache - 占位图:动态生成文件类型图标(PNG格式) - 重试机制:支持多次重试,耗尽后标记FAILED ### 错误处理机制 - 统一异常处理:BusinessErrorException、ResourceNotExistException - 错误码:ResultCodeEnum 定义 - 重试策略:网络重试与指数退避 - **更新** 缩略图错误:生成失败降级为占位图,超时返回202状态码 ### 重试策略 - 上传分片:失败重试 3 次,间隔递增 - 下载:超时重试 1 次 - 预览:失败降级为原始文件下载 - **更新** 缩略图:异步任务支持多次重试,同步回退超时返回202 ### 性能优化建议 - 分片大小与并发度调优 - 缩略图异步生成与缓存 - 预览服务集群与缓存 - 连接池与超时参数优化 - 限流与熔断保护 - **更新** 缩略图分布式锁避免重复生成,Redis缓存提升访问性能 **章节来源** - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [ThumbnailGenerationTask.java](file://crm-file/src/main/java/com/crm/file/task/ThumbnailGenerationTask.java) - [ThumbnailPlaceholderService.java](file://crm-file/src/main/java/com/crm/file/service/ThumbnailPlaceholderService.java) - [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) - [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) - [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java) - [ThumbnailDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/ThumbnailDTO.java)