coder-common-thin-backend/api/system/文件管理API.md
Leo aea2b1fbd7 docs: 新增完整的API接口文档
- 添加认证相关API文档(登录认证、验证码)
- 添加权限管理API文档(菜单管理、角色管理)
- 添加系统管理API文档(图片管理、文件管理、登录日志)
- 添加用户管理API文档
- 完善项目API文档结构,提升开发体验
2025-07-06 00:54:47 +08:00

867 lines
21 KiB
Markdown
Raw 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.

# 文件管理API
## 概述
文件管理模块提供文件上传、下载、存储管理等功能。支持多种文件类型,提供文件记录管理和批量操作功能。分为通用文件上传接口和系统文件记录管理两部分。
## 权限说明
文件管理接口需要相应的权限才能访问:
| 操作 | 权限码 | 说明 |
|------|--------|------|
| 查询文件列表 | `system:file:list` | 查看文件列表权限 |
| 上传文件 | `system:file:upload` | 上传文件权限 |
| 下载文件 | `system:file:download` | 下载文件权限 |
| 删除文件 | `system:file:remove` | 删除文件权限 |
## 文件上传接口
### 1. 上传文件(需认证)
**接口地址**: `POST /coder/file/uploadFile/{fileSize}/{folderName}/{fileParam}`
**接口描述**: 上传文件到服务器(需要登录认证)
**是否需要认证**: 是
**权限要求**: `system:file:upload`
**请求头**:
```
Authorization: Bearer your-token-value
Content-Type: multipart/form-data
```
**路径参数**:
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|--------|------|------|------|------|
| fileSize | Integer | 是 | 文件大小限制MB | 10 |
| folderName | String | 是 | 存储文件夹名称 | avatar |
| fileParam | String | 是 | 文件参数名 | file |
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| file | File | 是 | 上传的文件 |
**响应示例**:
```json
{
"status": 200,
"msg": "SUCCESS",
"data": {
"fileName": "avatar.jpg",
"originalName": "my-avatar.jpg",
"filePath": "/upload/avatar/2024/07/05/avatar_20240705_001.jpg",
"fileUrl": "http://localhost:18099/upload/avatar/2024/07/05/avatar_20240705_001.jpg",
"fileSize": 1024000,
"fileType": "jpg",
"uploadTime": "2024-07-05 10:00:00"
},
"traceId": "trace-123456"
}
```
**响应参数说明**:
| 参数名 | 类型 | 说明 |
|--------|------|------|
| fileName | String | 存储文件名 |
| originalName | String | 原始文件名 |
| filePath | String | 文件相对路径 |
| fileUrl | String | 文件访问URL |
| fileSize | Long | 文件大小(字节) |
| fileType | String | 文件类型 |
| uploadTime | String | 上传时间 |
**调用示例**:
```bash
curl -X POST \
http://localhost:18099/coder/file/uploadFile/10/avatar/file \
-H "Authorization: Bearer your-token-value" \
-F "file=@avatar.jpg"
```
**前端使用示例**:
```javascript
// 使用FormData上传文件
function uploadFile(file, folder, maxSize) {
const formData = new FormData();
formData.append('file', file);
fetch(`/coder/file/uploadFile/${maxSize}/${folder}/file`, {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + localStorage.getItem('token')
},
body: formData
})
.then(response => response.json())
.then(data => {
if (data.status === 200) {
console.log('上传成功:', data.data.fileUrl);
} else {
console.error('上传失败:', data.msg);
}
});
}
```
---
### 2. 匿名上传文件
**接口地址**: `POST /coder/file/uploadAnyFile/{fileSize}/{folderName}/{fileParam}`
**接口描述**: 匿名上传文件到服务器(无需登录认证)
**是否需要认证**: 否
**权限要求**: 无
**路径参数**: 同上传文件接口
**请求参数**: 同上传文件接口
**响应示例**: 同上传文件接口
**调用示例**:
```bash
curl -X POST \
http://localhost:18099/coder/file/uploadAnyFile/5/temp/file \
-F "file=@document.pdf"
```
**使用场景**:
- 用户注册时上传头像
- 访客上传临时文件
- 公开资源上传
---
## 系统文件记录管理接口
### 1. 分页查询文件列表
**接口地址**: `GET /coder/sysFile/listPage`
**接口描述**: 分页查询系统文件记录列表
**是否需要认证**: 是
**权限要求**: `system:file:list`
**请求头**:
```
Authorization: Bearer your-token-value
```
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|--------|------|------|------|------|
| pageNo | Integer | 否 | 页码 | 1 |
| pageSize | Integer | 否 | 每页大小 | 10 |
| fileName | String | 否 | 文件名称 | avatar.jpg |
| fileType | String | 否 | 文件类型 | jpg |
| folderName | String | 否 | 文件夹名称 | avatar |
| beginTime | String | 否 | 开始时间 | 2024-01-01 |
| endTime | String | 否 | 结束时间 | 2024-12-31 |
**响应示例**:
```json
{
"status": 200,
"msg": "SUCCESS",
"data": {
"records": [
{
"fileId": 1,
"fileName": "avatar_20240705_001.jpg",
"originalName": "my-avatar.jpg",
"filePath": "/upload/avatar/2024/07/05/avatar_20240705_001.jpg",
"fileUrl": "http://localhost:18099/upload/avatar/2024/07/05/avatar_20240705_001.jpg",
"folderName": "avatar",
"fileSize": 1024000,
"fileType": "jpg",
"contentType": "image/jpeg",
"fileStatus": "0",
"uploadUserId": 1,
"uploadUserName": "admin",
"remark": "用户头像",
"createBy": "admin",
"createTime": "2024-07-05 10:00:00",
"updateBy": "admin",
"updateTime": "2024-07-05 10:00:00"
}
],
"total": 1,
"size": 10,
"current": 1,
"pages": 1
},
"traceId": "trace-123456"
}
```
**调用示例**:
```bash
curl -X GET \
"http://localhost:18099/coder/sysFile/listPage?pageNo=1&pageSize=10&fileName=avatar" \
-H "Authorization: Bearer your-token-value"
```
---
### 2. 查询所有文件
**接口地址**: `GET /coder/sysFile/list`
**接口描述**: 查询所有系统文件记录(不分页)
**是否需要认证**: 是
**权限要求**: `system:file:list`
**请求参数**: 同分页查询除pageNo、pageSize外
**响应示例**:
```json
{
"status": 200,
"msg": "SUCCESS",
"data": [
{
"fileId": 1,
"fileName": "avatar_20240705_001.jpg",
"originalName": "my-avatar.jpg",
"filePath": "/upload/avatar/2024/07/05/avatar_20240705_001.jpg",
"fileUrl": "http://localhost:18099/upload/avatar/2024/07/05/avatar_20240705_001.jpg",
"folderName": "avatar",
"fileSize": 1024000,
"fileType": "jpg",
"contentType": "image/jpeg",
"fileStatus": "0",
"uploadUserId": 1,
"uploadUserName": "admin",
"remark": "用户头像",
"createBy": "admin",
"createTime": "2024-07-05 10:00:00",
"updateBy": "admin",
"updateTime": "2024-07-05 10:00:00"
}
],
"traceId": "trace-123456"
}
```
**调用示例**:
```bash
curl -X GET \
"http://localhost:18099/coder/sysFile/list?fileType=jpg" \
-H "Authorization: Bearer your-token-value"
```
---
### 3. 根据ID查询文件
**接口地址**: `GET /coder/sysFile/getById/{id}`
**接口描述**: 根据文件ID查询文件详细信息
**是否需要认证**: 是
**权限要求**: `system:file:list`
**路径参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| id | Long | 是 | 文件ID |
**响应示例**:
```json
{
"status": 200,
"msg": "SUCCESS",
"data": {
"fileId": 1,
"fileName": "avatar_20240705_001.jpg",
"originalName": "my-avatar.jpg",
"filePath": "/upload/avatar/2024/07/05/avatar_20240705_001.jpg",
"fileUrl": "http://localhost:18099/upload/avatar/2024/07/05/avatar_20240705_001.jpg",
"folderName": "avatar",
"fileSize": 1024000,
"fileType": "jpg",
"contentType": "image/jpeg",
"fileStatus": "0",
"uploadUserId": 1,
"uploadUserName": "admin",
"remark": "用户头像",
"createBy": "admin",
"createTime": "2024-07-05 10:00:00",
"updateBy": "admin",
"updateTime": "2024-07-05 10:00:00"
},
"traceId": "trace-123456"
}
```
**调用示例**:
```bash
curl -X GET \
http://localhost:18099/coder/sysFile/getById/1 \
-H "Authorization: Bearer your-token-value"
```
---
### 4. 新增文件记录
**接口地址**: `POST /coder/sysFile/add`
**接口描述**: 新增系统文件记录
**是否需要认证**: 是
**权限要求**: `system:file:upload`
**请求参数**:
```json
{
"fileName": "document_20240705_001.pdf",
"originalName": "重要文档.pdf",
"filePath": "/upload/documents/2024/07/05/document_20240705_001.pdf",
"fileUrl": "http://localhost:18099/upload/documents/2024/07/05/document_20240705_001.pdf",
"folderName": "documents",
"fileSize": 2048000,
"fileType": "pdf",
"contentType": "application/pdf",
"fileStatus": "0",
"uploadUserId": 1,
"uploadUserName": "admin",
"remark": "重要文档"
}
```
**请求参数说明**:
| 参数名 | 类型 | 必填 | 说明 | 校验规则 |
|--------|------|------|------|----------|
| fileName | String | 是 | 存储文件名 | 不能为空 |
| originalName | String | 是 | 原始文件名 | 不能为空 |
| filePath | String | 是 | 文件相对路径 | 不能为空 |
| fileUrl | String | 是 | 文件访问URL | 不能为空 |
| folderName | String | 是 | 文件夹名称 | 不能为空 |
| fileSize | Long | 是 | 文件大小 | 必须大于0 |
| fileType | String | 是 | 文件类型 | 不能为空 |
| contentType | String | 是 | MIME类型 | 不能为空 |
| fileStatus | String | 是 | 文件状态 | 0-正常 1-删除 |
| uploadUserId | Long | 否 | 上传用户ID | 有效的用户ID |
| uploadUserName | String | 否 | 上传用户名 | 可为空 |
| remark | String | 否 | 备注信息 | 最长200字符 |
**响应示例**:
```json
{
"status": 200,
"msg": "SUCCESS",
"data": "新增成功",
"traceId": "trace-123456"
}
```
**调用示例**:
```bash
curl -X POST \
http://localhost:18099/coder/sysFile/add \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-token-value" \
-d '{
"fileName": "document_20240705_001.pdf",
"originalName": "重要文档.pdf",
"filePath": "/upload/documents/2024/07/05/document_20240705_001.pdf",
"fileUrl": "http://localhost:18099/upload/documents/2024/07/05/document_20240705_001.pdf",
"folderName": "documents",
"fileSize": 2048000,
"fileType": "pdf",
"contentType": "application/pdf",
"fileStatus": "0",
"uploadUserId": 1,
"uploadUserName": "admin",
"remark": "重要文档"
}'
```
---
### 5. 修改文件信息
**接口地址**: `POST /coder/sysFile/update`
**接口描述**: 修改系统文件记录信息
**是否需要认证**: 是
**权限要求**: `system:file:edit`
**请求参数**:
```json
{
"fileId": 1,
"fileName": "document_20240705_001.pdf",
"originalName": "重要文档.pdf",
"filePath": "/upload/documents/2024/07/05/document_20240705_001.pdf",
"fileUrl": "http://localhost:18099/upload/documents/2024/07/05/document_20240705_001.pdf",
"folderName": "documents",
"fileSize": 2048000,
"fileType": "pdf",
"contentType": "application/pdf",
"fileStatus": "0",
"uploadUserId": 1,
"uploadUserName": "admin",
"remark": "重要文档(已更新)"
}
```
**请求参数说明**:
| 参数名 | 类型 | 必填 | 说明 | 校验规则 |
|--------|------|------|------|----------|
| fileId | Long | 是 | 文件ID | 必须是有效的文件ID |
| 其他参数 | - | - | 同新增文件记录 | - |
**响应示例**:
```json
{
"status": 200,
"msg": "SUCCESS",
"data": "修改成功",
"traceId": "trace-123456"
}
```
**调用示例**:
```bash
curl -X POST \
http://localhost:18099/coder/sysFile/update \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-token-value" \
-d '{
"fileId": 1,
"fileName": "document_20240705_001.pdf",
"originalName": "重要文档.pdf",
"remark": "重要文档(已更新)"
}'
```
---
### 6. 删除文件
**接口地址**: `POST /coder/sysFile/deleteById/{id}`
**接口描述**: 根据ID删除文件记录和物理文件
**是否需要认证**: 是
**权限要求**: `system:file:remove`
**路径参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| id | Long | 是 | 文件ID |
**响应示例**:
```json
{
"status": 200,
"msg": "SUCCESS",
"data": "删除成功",
"traceId": "trace-123456"
}
```
**调用示例**:
```bash
curl -X POST \
http://localhost:18099/coder/sysFile/deleteById/1 \
-H "Authorization: Bearer your-token-value"
```
---
### 7. 批量删除文件
**接口地址**: `POST /coder/sysFile/batchDelete`
**接口描述**: 批量删除文件记录和物理文件
**是否需要认证**: 是
**权限要求**: `system:file:remove`
**请求参数**:
```json
{
"ids": [1, 2, 3]
}
```
**请求参数说明**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| ids | Long[] | 是 | 文件ID数组 |
**响应示例**:
```json
{
"status": 200,
"msg": "SUCCESS",
"data": "删除成功",
"traceId": "trace-123456"
}
```
**调用示例**:
```bash
curl -X POST \
http://localhost:18099/coder/sysFile/batchDelete \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-token-value" \
-d '{
"ids": [1, 2, 3]
}'
```
---
## 文件字段说明
### 基础字段
| 字段名 | 类型 | 说明 | 示例 |
|--------|------|------|------|
| fileId | Long | 文件ID | 1 |
| fileName | String | 存储文件名 | avatar_20240705_001.jpg |
| originalName | String | 原始文件名 | my-avatar.jpg |
| filePath | String | 文件相对路径 | /upload/avatar/2024/07/05/avatar_20240705_001.jpg |
| fileUrl | String | 文件访问URL | http://localhost:18099/upload/avatar/2024/07/05/avatar_20240705_001.jpg |
### 分类字段
| 字段名 | 类型 | 说明 | 示例 |
|--------|------|------|------|
| folderName | String | 文件夹名称 | avatar |
| fileType | String | 文件扩展名 | jpg |
| contentType | String | MIME类型 | image/jpeg |
| fileSize | Long | 文件大小(字节) | 1024000 |
### 状态字段
| 字段名 | 类型 | 说明 | 示例 |
|--------|------|------|------|
| fileStatus | String | 文件状态 | 0-正常 1-删除 |
| uploadUserId | Long | 上传用户ID | 1 |
| uploadUserName | String | 上传用户名 | admin |
| remark | String | 备注信息 | 用户头像 |
---
## 数据字典
### 文件状态 (fileStatus)
| 值 | 说明 |
|----|------|
| 0 | 正常 |
| 1 | 已删除 |
### 常见文件类型
| 文件类型 | 扩展名 | MIME类型 | 说明 |
|----------|--------|----------|------|
| 图片 | jpg, jpeg, png, gif, bmp | image/* | 图片文件 |
| 文档 | pdf, doc, docx, xls, xlsx, ppt, pptx | application/* | 办公文档 |
| 音频 | mp3, wav, flac, aac | audio/* | 音频文件 |
| 视频 | mp4, avi, mov, wmv | video/* | 视频文件 |
| 压缩包 | zip, rar, 7z, tar, gz | application/* | 压缩文件 |
| 文本 | txt, md, csv | text/* | 文本文件 |
---
## 文件配置
### 1. 文件存储配置
```yaml
# application-dev.yml
coder:
# 文件存储路径
filePath: /data/upload/
# 文件访问域名
domain: http://localhost:18099
# 文件大小限制MB
maxFileSize: 100
# 允许的文件类型
allowedTypes:
- jpg
- jpeg
- png
- gif
- pdf
- doc
- docx
- xls
- xlsx
# 禁止的文件类型
forbiddenTypes:
- exe
- bat
- sh
- jsp
- php
```
### 2. 文件夹分类
```java
// 文件夹类型枚举
public enum FolderType {
AVATAR("avatar", "用户头像"),
DOCUMENT("document", "文档文件"),
IMAGE("image", "图片文件"),
TEMP("temp", "临时文件"),
EXPORT("export", "导出文件");
private final String code;
private final String name;
}
```
### 3. 文件上传工具类
```java
@Component
public class FileUploadUtil {
/**
* 上传文件
*/
public FileUploadResult uploadFile(MultipartFile file, String folder, int maxSize) {
// 1. 文件校验
validateFile(file, maxSize);
// 2. 生成文件名
String fileName = generateFileName(file.getOriginalFilename());
// 3. 创建目录
String datePath = DateUtil.format(new Date(), "yyyy/MM/dd");
String dirPath = filePath + folder + "/" + datePath + "/";
FileUtil.createDirs(dirPath);
// 4. 保存文件
String filePath = dirPath + fileName;
file.transferTo(new File(filePath));
// 5. 生成访问URL
String fileUrl = domain + "/upload/" + folder + "/" + datePath + "/" + fileName;
// 6. 返回结果
return FileUploadResult.builder()
.fileName(fileName)
.originalName(file.getOriginalFilename())
.filePath(filePath)
.fileUrl(fileUrl)
.fileSize(file.getSize())
.fileType(FileUtil.getExtension(fileName))
.uploadTime(new Date())
.build();
}
/**
* 文件校验
*/
private void validateFile(MultipartFile file, int maxSize) {
if (file.isEmpty()) {
throw new BusinessException("文件不能为空");
}
if (file.getSize() > maxSize * 1024 * 1024) {
throw new BusinessException("文件大小不能超过" + maxSize + "MB");
}
String extension = FileUtil.getExtension(file.getOriginalFilename());
if (!allowedTypes.contains(extension.toLowerCase())) {
throw new BusinessException("不支持的文件类型:" + extension);
}
if (forbiddenTypes.contains(extension.toLowerCase())) {
throw new BusinessException("禁止上传的文件类型:" + extension);
}
}
/**
* 生成文件名
*/
private String generateFileName(String originalName) {
String extension = FileUtil.getExtension(originalName);
String baseName = FileUtil.getBaseName(originalName);
String timestamp = DateUtil.format(new Date(), "yyyyMMdd_HHmmss");
String random = RandomUtil.randomString(3);
return baseName + "_" + timestamp + "_" + random + "." + extension;
}
}
```
---
## 错误码说明
| 错误码 | 错误信息 | 说明 |
|--------|----------|------|
| 400 | 文件不能为空 | 上传文件为空 |
| 400 | 文件大小不能超过{size}MB | 文件大小超过限制 |
| 400 | 不支持的文件类型 | 文件类型不在允许列表中 |
| 400 | 禁止上传的文件类型 | 文件类型在禁止列表中 |
| 400 | 文件名不能为空 | 文件名为空 |
| 400 | 文件路径不能为空 | 文件路径为空 |
| 400 | 文件不存在 | 文件ID不存在 |
| 400 | 文件已被删除 | 文件状态为已删除 |
| 401 | 当前会话未登录 | 未登录或Token无效 |
| 403 | 权限不足 | 没有相应的操作权限 |
| 500 | 文件上传失败 | 文件保存到磁盘失败 |
| 500 | 文件删除失败 | 物理文件删除失败 |
| 500 | 磁盘空间不足 | 服务器磁盘空间不足 |
---
## 安全特性
### 1. 文件类型验证
- **扩展名校验**: 验证文件扩展名
- **MIME类型校验**: 验证文件MIME类型
- **文件内容校验**: 验证文件真实类型
- **黑名单过滤**: 禁止上传危险文件类型
### 2. 文件大小限制
- **单文件大小限制**: 限制单个文件大小
- **总文件大小限制**: 限制用户总文件大小
- **磁盘空间检查**: 检查服务器磁盘空间
### 3. 访问控制
- **权限验证**: 验证用户上传和访问权限
- **路径防护**: 防止路径遍历攻击
- **防盗链**: 防止文件被盗链
### 4. 病毒扫描
- **文件扫描**: 上传文件病毒扫描
- **隔离机制**: 可疑文件隔离处理
- **定期扫描**: 定期扫描存储文件
---
## 性能优化
### 1. 文件存储
- **分目录存储**: 按日期和类型分目录存储
- **CDN加速**: 使用CDN加速文件访问
- **压缩存储**: 自动压缩图片文件
- **缓存策略**: 设置合适的缓存策略
### 2. 上传优化
- **分片上传**: 大文件分片上传
- **断点续传**: 支持断点续传功能
- **并发上传**: 支持多文件并发上传
- **进度显示**: 实时显示上传进度
### 3. 存储优化
- **重复文件检测**: 检测并避免重复文件
- **文件压缩**: 自动压缩文件
- **定期清理**: 清理临时文件和无效文件
- **存储监控**: 监控存储空间使用情况
---
## 使用建议
### 1. 文件命名规范
- **唯一性**: 确保文件名唯一
- **时间戳**: 包含时间戳信息
- **随机性**: 添加随机字符
- **可读性**: 保持一定的可读性
### 2. 文件分类管理
- **按类型分类**: 不同类型文件存储在不同目录
- **按用户分类**: 不同用户文件分开存储
- **按时间分类**: 按年月日创建目录结构
- **按业务分类**: 按业务模块分类存储
### 3. 安全防护
- **输入验证**: 严格验证上传文件
- **权限控制**: 细粒度的权限控制
- **日志记录**: 记录所有文件操作
- **备份策略**: 重要文件定期备份
### 4. 监控告警
- **存储监控**: 监控存储空间使用
- **性能监控**: 监控上传下载性能
- **安全监控**: 监控异常文件操作
- **容量告警**: 存储空间不足告警
---
## 注意事项
1. **文件安全**: 严格验证上传文件类型和内容
2. **存储路径**: 确保文件存储路径安全
3. **权限控制**: 合理设置文件访问权限
4. **磁盘空间**: 定期清理无效文件,避免磁盘满
5. **备份策略**: 重要文件需要备份
6. **访问控制**: 防止文件被恶意访问
7. **性能考虑**: 大文件上传时注意性能影响
8. **并发控制**: 处理并发上传时的文件冲突
9. **错误处理**: 完善的错误处理和回滚机制
10. **日志审计**: 记录所有文件操作日志