- 添加认证相关API文档(登录认证、验证码) - 添加权限管理API文档(菜单管理、角色管理) - 添加系统管理API文档(图片管理、文件管理、登录日志) - 添加用户管理API文档 - 完善项目API文档结构,提升开发体验
867 lines
21 KiB
Markdown
867 lines
21 KiB
Markdown
# 文件管理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. **日志审计**: 记录所有文件操作日志 |