nms-files 是一个面向个人项目和内部系统的文件中间件服务,设计初衷是“后端服务调用后端服务”。它不直接承担业务权限、用户体系或公网匿名文件站点职责,而是为业务后端提供统一的文件上传、存储、下载、预览、回收站和清理能力。
本项目适合作为内网文件能力后端接入,推荐部署在业务系统可访问的内部网络中。
核心定位:
APP_API_KEY。不适用场景:
Range 请求。推荐接入链路:
浏览器 / 客户端
-> 接入方业务后端
-> nms-files
接入方后端需要持有 APP_API_KEY,调用本服务时统一携带:
X-API-Key: <your-api-key>
典型上传流程:
POST /api/files/upload。id、file_key、fixed_link、display_name、mime_type、size 等字段。典型下载流程:
建议透传的响应头:
Content-TypeContent-DispositionContent-LengthContent-RangeAccept-Ranges基于 .env.example 创建 .env:
Copy-Item ".env.example" ".env"
关键配置:
APP_NAME=nms-files
APP_ENV=local
APP_HOST=0.0.0.0
APP_PORT=8000
APP_API_KEY=change-me
MYSQL_HOST=mysql
MYSQL_PORT=3306
MYSQL_DB=nms_files
MYSQL_USER=nms_files
MYSQL_PASSWORD=nms_files
FILE_ROOT=/data/files
MAX_UPLOAD_SIZE_MB=100
RECYCLE_RETENTION_DAYS=180
RECYCLE_CLEANUP_CRON=0 3 * * *
BLOB_CLEANUP_CRON=30 3 * * *
REF_COUNT_REPAIR_CRON=0 4 * * *
说明:
APP_API_KEY 是服务间调用密钥,生产环境必须修改。FILE_ROOT 是容器内文件根目录,docker-compose 默认挂载到宿主机 ./data/files。./data/mysql。Asia/Shanghai 时区。使用 Docker 启动:
docker-compose up --build
执行数据库迁移:
alembic upgrade head
默认端口:
80003306健康检查:
curl -X GET "http://127.0.0.1:8000/api/system/health" `
-H "X-API-Key: change-me"
所有接口都需要鉴权请求头:
X-API-Key: <your-api-key>
固定链接接口也需要鉴权。固定链接是稳定资源地址,不是匿名外链。
常见状态码:
200:请求成功。206:Range 分段请求成功。400:请求参数错误,或文件类型不支持预览。401:API Key 缺失或错误。404:文件不存在、文件在回收站、或物理文件缺失。413:上传文件超过大小限制。416:Range 请求不合法。500:服务内部错误。| 模块 | 方法 | 路径 | 说明 |
|---|---|---|---|
| 系统 | GET | /api/system/health | 健康检查 |
| 文件 | POST | /api/files/upload | 上传文件 |
| 文件 | GET | /api/files | 查询文件列表 |
| 文件 | GET | /api/files/{record_id} | 查询文件详情 |
| 文件 | PATCH | /api/files/{record_id} | 重命名文件 |
| 文件 | GET | /api/files/{record_id}/download | 按记录 ID 下载文件 |
| 文件 | DELETE | /api/files/{record_id} | 删除到回收站 |
| 文件 | POST | /api/files/{record_id}/restore | 从回收站恢复 |
| 文件 | GET | /api/files/key/{file_key} | 按固定链接标识下载文件 |
| 预览 | GET | /api/files/preview/{record_id} | 预览文件 |
| 回收站 | GET | /api/recycle | 查询回收站列表 |
| 运维任务 | POST | /api/tasks/recycle-cleanup | 手动清理超期回收站记录 |
| 运维任务 | POST | /api/tasks/blob-cleanup | 手动清理无引用物理文件 |
| 运维任务 | POST | /api/tasks/ref-count-repair | 手动修复引用计数 |
以下示例假设:
http://127.0.0.1:8000change-meGET /api/system/health
X-API-Key: change-me
curl -X GET "http://127.0.0.1:8000/api/system/health" `
-H "X-API-Key: change-me"
响应示例:
{
"status": "ok",
"database": "ok"
}
POST /api/files/upload
X-API-Key: change-me
Content-Type: multipart/form-data
表单字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
upload_file | file | 是 | 上传文件 |
curl -X POST "http://127.0.0.1:8000/api/files/upload" `
-H "X-API-Key: change-me" `
-F "upload_file=@D:/tmp/demo.pdf"
响应示例:
{
"file": {
"id": 1,
"file_key": "8d2d4f4b2a7a4e01b4e9c9ed6a9b34c1",
"fixed_link": "/api/files/key/8d2d4f4b2a7a4e01b4e9c9ed6a9b34c1",
"original_file_name": "demo.pdf",
"display_name": "demo.pdf",
"file_ext": "pdf",
"size": 1024,
"mime_type": "application/pdf",
"is_deleted": false,
"deleted_at": null,
"created_at": "2026-05-23T10:00:00",
"updated_at": "2026-05-23T10:00:00"
},
"fixed_link": "/api/files/key/8d2d4f4b2a7a4e01b4e9c9ed6a9b34c1"
}
GET /api/files?query=&mime_type=&is_deleted=false&page=1&page_size=20
X-API-Key: change-me
查询参数:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
query | string | 否 | 无 | 按展示文件名或原始文件名模糊搜索 |
mime_type | string | 否 | 无 | 按 MIME 类型精确过滤 |
is_deleted | boolean | 否 | false | 是否查询回收站文件 |
page | integer | 否 | 1 | 页码,最小为 1 |
page_size | integer | 否 | 20 | 每页数量,范围 1 到 100 |
curl -X GET "http://127.0.0.1:8000/api/files?page=1&page_size=20" `
-H "X-API-Key: change-me"
响应示例:
{
"items": [
{
"id": 1,
"file_key": "8d2d4f4b2a7a4e01b4e9c9ed6a9b34c1",
"fixed_link": "/api/files/key/8d2d4f4b2a7a4e01b4e9c9ed6a9b34c1",
"original_file_name": "demo.pdf",
"display_name": "demo.pdf",
"file_ext": "pdf",
"size": 1024,
"mime_type": "application/pdf",
"is_deleted": false,
"deleted_at": null,
"created_at": "2026-05-23T10:00:00",
"updated_at": "2026-05-23T10:00:00"
}
],
"page": 1,
"page_size": 20
}
GET /api/files/{record_id}
X-API-Key: change-me
curl -X GET "http://127.0.0.1:8000/api/files/1" `
-H "X-API-Key: change-me"
响应为单个文件记录,字段同列表中的 items[]。
PATCH /api/files/{record_id}
X-API-Key: change-me
Content-Type: application/json
请求体:
{
"display_name": "new-name.pdf"
}
curl -X PATCH "http://127.0.0.1:8000/api/files/1" `
-H "X-API-Key: change-me" `
-H "Content-Type: application/json" `
-d "{\"display_name\":\"new-name.pdf\"}"
说明:
file_key 和 fixed_link。GET /api/files/{record_id}/download
X-API-Key: change-me
Range: bytes=0-1023
Range 请求头可选。
curl -X GET "http://127.0.0.1:8000/api/files/1/download" `
-H "X-API-Key: change-me" `
-o "demo.pdf"
分段下载示例:
curl -X GET "http://127.0.0.1:8000/api/files/1/download" `
-H "X-API-Key: change-me" `
-H "Range: bytes=0-1023" `
-o "demo.part"
说明:
200。206。GET /api/files/key/{file_key}
X-API-Key: change-me
Range: bytes=0-1023
curl -X GET "http://127.0.0.1:8000/api/files/key/8d2d4f4b2a7a4e01b4e9c9ed6a9b34c1" `
-H "X-API-Key: change-me" `
-o "demo.pdf"
说明:
fixed_link 字段返回的是相对路径。X-API-Key。DELETE /api/files/{record_id}
X-API-Key: change-me
curl -X DELETE "http://127.0.0.1:8000/api/files/1" `
-H "X-API-Key: change-me"
说明:
RECYCLE_RETENTION_DAYS 后,定时任务会清理回收站记录。POST /api/files/{record_id}/restore
X-API-Key: change-me
curl -X POST "http://127.0.0.1:8000/api/files/1/restore" `
-H "X-API-Key: change-me"
说明:
file_key 和 fixed_link。400。GET /api/files/preview/{record_id}
X-API-Key: change-me
Range: bytes=0-1023
Range 请求头可选。
curl -X GET "http://127.0.0.1:8000/api/files/preview/1" `
-H "X-API-Key: change-me"
说明:
Content-Disposition: inline。400。GET /api/recycle?query=&mime_type=&page=1&page_size=20
X-API-Key: change-me
查询参数:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
query | string | 否 | 无 | 按展示文件名或原始文件名模糊搜索 |
mime_type | string | 否 | 无 | 按 MIME 类型精确过滤 |
page | integer | 否 | 1 | 页码,最小为 1 |
page_size | integer | 否 | 20 | 每页数量,范围 1 到 100 |
curl -X GET "http://127.0.0.1:8000/api/recycle?page=1&page_size=20" `
-H "X-API-Key: change-me"
响应结构同文件列表。
POST /api/tasks/recycle-cleanup
X-API-Key: change-me
curl -X POST "http://127.0.0.1:8000/api/tasks/recycle-cleanup" `
-H "X-API-Key: change-me"
响应示例:
{
"result": 3
}
说明:
POST /api/tasks/blob-cleanup
X-API-Key: change-me
curl -X POST "http://127.0.0.1:8000/api/tasks/blob-cleanup" `
-H "X-API-Key: change-me"
响应示例:
{
"result": 1
}
说明:
PENDING_DELETE 且引用计数为 0 的物理文件。POST /api/tasks/ref-count-repair
X-API-Key: change-me
curl -X POST "http://127.0.0.1:8000/api/tasks/ref-count-repair" `
-H "X-API-Key: change-me"
响应示例:
{
"result": 2
}
说明:
file_record 重新计算 file_blob.ref_count。接入方建议至少保存以下字段:
id:适合管理接口操作,例如重命名、删除、恢复、详情查询。file_key:稳定文件标识,可用于拼装固定链接。fixed_link:稳定访问路径,适合长期保存。display_name:展示文件名。mime_type:文件类型。size:文件大小,单位为字节。不建议保存或暴露:
APP_API_KEY。应用启动时会注册以下定时任务:
RECYCLE_CLEANUP_CRON:清理超期回收站记录。BLOB_CLEANUP_CRON:清理无引用物理文件。REF_COUNT_REPAIR_CRON:修复引用计数。任务接口主要用于手动补偿和排查,不建议纳入普通业务请求链路。
升级或迁移前需要保护:
.env./data/files./data/mysql推荐升级步骤:
.env、文件目录和 MySQL 数据目录。alembic upgrade head。/api/system/health。Content type
Image
Digest
sha256:5f346ccbe…
Size
64 MB
Last updated
2 months ago
docker pull muziyuyang/nms-files