# file-service **Repository Path**: SYaixiang/file-service ## Basic Information - **Project Name**: file-service - **Description**: python语言的文件上传后端服务,FastApi、Minio、Mysql - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 6 - **Forks**: 0 - **Created**: 2025-03-04 - **Last Updated**: 2025-11-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: Python ## README # 文件服务系统 (File Service) ![version](https://img.shields.io/badge/version-0.2.1-blue.svg) ![python](https://img.shields.io/badge/python-3.8+-green.svg) ![fastapi](https://img.shields.io/badge/fastapi-0.100.0+-brightgreen.svg) ![minio](https://img.shields.io/badge/minio-7.2.0-yellow.svg) 基于 FastAPI 和 MinIO 构建的文件服务系统,提供文件上传、存储、管理等功能。 ## 功能特性 - 文件上传与存储 - 支持多种文件类型(图片、视频、音频、文档等) - 自动提取文件创建时间(从文件元数据或文件名) - 基于日期的目录结构 - 文件去重(基于哈希值) - 文件名保留 + 哈希值标识 - **支持断点续传**(大文件分片上传) - 文件管理 - 文件列表查询(支持分页、过滤) - 文件预览(支持所有类型文件) - 文件下载 - 文件重命名 - 回收站功能(软删除) - 永久删除 - 批量删除(支持多文件同时删除) - **逻辑目录管理** - 创建多级目录结构 - 移动文件至指定目录 - 支持目录树显示 - 按目录查询文件 - 支持目录重命名和移动 - 支持同时移动多个文件和目录到指定目录 - 支持目录删除(包含子目录和文件) - **无感增量备份** - 增量备份(仅备份修改过的文件) - 全量备份(备份所有文件) - 自动定时备份(每日/每周/每月) - 备份任务管理 - 文件快速恢复 - 批量恢复 - 支持指定目录备份 - 用户认证 - 用户注册 - 用户登录(JWT认证) - 令牌验证 ## API 接口 系统提供完整的中文API文档,可通过访问 `/docs` 路径查看交互式API文档。API接口按功能分组为: - **认证**:用户注册、登录等认证接口(公开接口,无需认证) - **文件上传**:文件上传相关接口(需要认证) - **断点上传**:大文件分片上传相关接口(需要认证) - **文件管理**:文件查询、预览、下载、删除等管理接口(需要认证) - **目录管理**:目录创建、查询、修改、删除等管理接口(需要认证) - **备份管理**:备份任务创建、执行、恢复等管理接口(需要认证) ### 认证相关 #### 用户注册 ``` POST /auth/register ``` 请求体: ```json { "username": "string", "email": "user@example.com", "password": "string" } ``` 响应: ```json { "code": 200, "message": "注册成功", "data": null, "timestamp": "2024-03-14T10:00:00.000Z" } ``` #### 用户登录 ``` POST /auth/login ``` 请求体: ```json { "username": "string", "password": "string" } ``` 响应: ```json { "code": 200, "message": "登录成功", "data": { "access_token": "string", "refresh_token": "string", "token_type": "bearer", "user": { "id": 1, "username": "string", "email": "user@example.com" } }, "timestamp": "2024-03-14T10:00:00.000Z" } ``` #### 刷新令牌 ``` POST /auth/refresh ``` 请求体: ```json { "refresh_token": "string" } ``` 响应: ```json { "code": 200, "message": "令牌刷新成功", "data": { "access_token": "string", "refresh_token": "string", "token_type": "bearer", "user": { "id": 1, "username": "string", "email": "user@example.com" } }, "timestamp": "2024-03-14T10:00:00.000Z" } ``` ### 断点上传 断点上传适用于大文件(>50MB),支持文件分片上传、断点续传、进度查询等功能。 #### 初始化分片上传 ``` POST /api/chunk-upload/init ``` 请求体: ```json { "file_name": "large_file.mp4", "file_size": 1073741824, "chunk_size": 5242880, "mime_type": "video/mp4", "directory_id": 1 // 可选,上传到指定目录,为0表示上传到根目录 } ``` 响应: ```json { "code": 200, "message": "初始化分片上传成功", "data": { "task_id": "550e8400-e29b-41d4-a716-446655440000", "upload_id": "VXBsb2FkIElEIGZvciA1oc...", "chunk_size": 5242880, "total_chunks": 205, "expires_at": "2024-03-21T10:00:00.000Z" }, "timestamp": "2024-03-14T10:00:00.000Z" } ``` #### 上传文件分片 ``` POST /api/chunk-upload/upload-chunk?task_id={task_id}&chunk_number={chunk_number} ``` 请求: - Content-Type: multipart/form-data - 参数: - task_id: 任务ID - chunk_number: 分片序号(从1开始) - file: 分片内容 响应: ```json { "code": 200, "message": "分片上传成功", "data": { "task_id": "550e8400-e29b-41d4-a716-446655440000", "chunk_number": 1, "etag": "a1b2c3d4e5f6g7h8i9j0", "uploaded_chunks": 1, "total_chunks": 205 }, "timestamp": "2024-03-14T10:00:00.000Z" } ``` #### 获取上传状态 ``` GET /api/chunk-upload/status/{task_id} ``` 响应: ```json { "code": 200, "message": "获取上传状态成功", "data": { "task_id": "550e8400-e29b-41d4-a716-446655440000", "file_name": "large_file.mp4", "file_size": 1073741824, "status": "uploading", "uploaded_chunks": 100, "total_chunks": 205, "progress": 48.78, "chunks": [ {"chunk_number": 1, "status": "uploaded"}, {"chunk_number": 2, "status": "uploaded"}, // ... {"chunk_number": 205, "status": "pending"} ], "create_time": "2024-03-14T10:00:00.000Z", "update_time": "2024-03-14T10:15:00.000Z", "expires_at": "2024-03-21T10:00:00.000Z", "directory_id": 1 }, "timestamp": "2024-03-14T10:15:00.000Z" } ``` #### 完成上传 ``` POST /api/chunk-upload/complete ``` 请求体: ```json { "task_id": "550e8400-e29b-41d4-a716-446655440000" } ``` 响应: ```json { "code": 200, "message": "文件上传完成", "data": { "file_id": 1, "filename": "large_file_12345678.mp4", "original_filename": "large_file.mp4", "storage_path": "1/video/2024/03/14/large_file_12345678.mp4", "file_size": 1073741824, "content_type": "video/mp4", "file_type": "video", "create_time": "2024-03-14T10:30:00.000Z", "hash": "sha256hash", "is_duplicate": false, "directory_id": 1 }, "timestamp": "2024-03-14T10:30:00.000Z" } ``` #### 取消上传 ``` POST /api/chunk-upload/abort/{task_id} ``` 响应: ```json { "code": 200, "message": "上传任务已取消", "data": { "task_id": "550e8400-e29b-41d4-a716-446655440000", "message": "上传任务已取消" }, "timestamp": "2024-03-14T10:00:00.000Z" } ``` ### 文件管理 #### 上传文件 ``` POST /api/upload ``` 请求: - Content-Type: multipart/form-data - 参数: - file:文件 - directory_id:目录ID(可选,为0表示上传到根目录) - file_hash:文件哈希值(可选,如果提供则不再计算哈希) 响应: ```json { "code": 200, "message": "文件上传成功", "data": { "file_id": 1, "filename": "example.jpg", "original_filename": "photo.jpg", "storage_path": "1/photo/2024/03/14/example_12345678.jpg", "size": 1024, "content_type": "image/jpeg", "file_type": "photo", "create_time": "2024-03-14T10:00:00.000Z", "hash": "sha256hash", "is_duplicate": false, "directory_id": 0 }, "timestamp": "2024-03-14T10:00:00.000Z" } ``` #### 验证文件哈希 ``` POST /api/verify ``` 支持两种验证模式:单个哈希验证和批量哈希验证。 **1. 单个哈希验证** 请求体: ```json { "file_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" } ``` 响应: ```json { "code": 200, "message": "可以上传文件", "data": { "exists": false, "file_id": null, "upload_permission": true, "message": "文件不存在,可以上传" }, "timestamp": "2024-03-14T10:00:00.000Z" } ``` **2. 批量哈希验证** 请求体: ```json { "file_hashes": [ "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2" ] } ``` 响应: ```json { "code": 200, "message": "完成批量哈希验证,共2个,已存在1个", "data": { "results": [ { "file_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "exists": false, "file_id": null, "upload_permission": true }, { "file_hash": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2", "exists": true, "file_id": 42, "upload_permission": false } ], "total": 2, "exists_count": 1 }, "timestamp": "2024-03-14T10:00:00.000Z" } ``` #### 查询文件列表 ``` GET /api/files ``` 参数: - file_type: 文件类型(photo/video/audio/document/other) - start_time: 开始时间 (YYYY-MM-DD HH:MM:SS) - end_time: 结束时间 (YYYY-MM-DD HH:MM:SS) - keyword: 文件名关键词 - file_hash: 文件哈希值 - page: 页码(默认1) - page_size: 每页数量(默认20,最大100) - is_delete: 是否已删除(为空时查询所有文件,false查询未删除文件,true查询已删除文件) - directory_id: 目录ID(可选,为None表示查询所有目录的文件,0表示只查询根目录文件) 响应: ```json { "code": 200, "message": "查询成功", "data": { "total": 100, "page": 1, "page_size": 20, "items": [ { "id": 1, "user_id": 1, "file_name": "example.jpg", "file_path": "1/photo/2024/03/14/example_12345678.jpg", "file_type": "photo", "file_size": 1024, "hash": "sha256hash", "upload_time": "2024-03-14T10:00:00.000Z", "create_time": "2024-03-14T10:00:00.000Z", "extension": ".jpg", "mime_type": "image/jpeg", "remark": null, "is_deleted": false, "directory_id": 1 } ] }, "timestamp": "2024-03-14T10:00:00.000Z" } ``` #### 删除文件 ``` DELETE /api/files/{file_id} ``` 参数: - permanent: 是否永久删除(默认false) 响应: ```json { "code": 200, "message": "文件已移至回收站", "data": { "is_permanent": false }, "timestamp": "2024-03-14T10:00:00.000Z" } ``` #### 批量删除文件 > **注意:** 此接口已被弃用,请使用新的批量删除接口 `POST /api/directories/batch-delete` 代替。 ``` POST /api/files/batch-delete ``` 请求体: ```json { "file_ids": [1, 2, 3], "permanent": false } ``` 响应: ```json { "code": 200, "message": "成功删除 3 个文件", "data": { "success_count": 3, "failed_count": 0, "failed_files": [] }, "timestamp": "2024-03-14T10:00:00.000Z" } ``` #### 重命名文件 ``` PUT /api/files/{file_id}/rename ``` 参数: - new_name: 新文件名 响应: ```json { "code": 200, "message": "文件重命名成功", "data": { "new_name": "new_example.jpg" }, "timestamp": "2024-03-14T10:00:00.000Z" } ``` #### 批量恢复文件 ``` POST /api/files/batch-restore ``` 请求体: ```json { "file_ids": [1, 2, 3] } ``` 响应: ```json { "code": 200, "message": "成功恢复 3 个文件", "data": { "success_count": 3, "failed_count": 0, "failed_files": [] }, "timestamp": "2024-03-14T10:00:00.000Z" } ``` #### 获取文件预览链接 ``` GET /api/files/{file_id}/preview ``` 响应: ```json { "code": 200, "message": "获取预览链接成功", "data": { "url": "https://example.com/preview/...", "file_type": "photo", "mime_type": "image/jpeg", "file_name": "example.jpg", "file_size": 1024, "extension": ".jpg", "direct_preview": true }, "timestamp": "2024-03-14T10:00:00.000Z" } ``` #### 获取文件下载链接 ``` GET /api/files/{file_id}/download ``` 响应: ```json { "code": 200, "message": "获取下载链接成功", "data": { "url": "https://example.com/download/...", "file_name": "example.jpg", "file_size": 1024, "mime_type": "image/jpeg" }, "timestamp": "2024-03-14T10:00:00.000Z" } ``` ### 目录管理 #### 创建目录 ``` POST /api/directories ``` 请求体: ```json { "name": "照片集", "parent_id": 0 // 0表示根目录 } ``` 响应: ```json { "code": 200, "message": "目录创建成功", "data": { "id": 1, "name": "照片集", "parent_id": 0, "user_id": 1, "path": "/照片集", "create_time": "2024-05-15T12:00:00Z", "update_time": "2024-05-15T12:00:00Z", "is_deleted": false }, "timestamp": "2024-05-15T12:00:00Z" } ``` #### 获取目录列表 ``` GET /api/directories ``` 参数: - parent_id: 父目录ID,不传表示获取根目录下的目录(可选) 响应: ```json { "code": 200, "message": "获取目录列表成功", "data": { "items": [ { "id": 1, "name": "照片集", "parent_id": 0, "user_id": 1, "path": "/照片集", "create_time": "2024-05-15T12:00:00Z", "update_time": "2024-05-15T12:00:00Z", "is_deleted": false }, { "id": 2, "name": "文档", "parent_id": 0, "user_id": 1, "path": "/文档", "create_time": "2024-05-15T12:05:00Z", "update_time": "2024-05-15T12:05:00Z", "is_deleted": false } ] }, "timestamp": "2024-05-15T12:10:00Z" } ``` #### 获取目录树 ``` GET /api/directories/tree ``` 响应: ```json { "code": 200, "message": "获取目录树成功", "data": { "tree": [ { "id": 1, "name": "照片集", "path": "/照片集", "parent_id": 0, "children": [ { "id": 3, "name": "2023年", "path": "/照片集/2023年", "parent_id": 1, "children": [], "file_count": 5 } ], "file_count": 2 }, { "id": 2, "name": "文档", "path": "/文档", "parent_id": 0, "children": [], "file_count": 3 } ] }, "timestamp": "2024-05-15T12:15:00Z" } ``` #### 获取目录详情 ``` GET /api/directories/{directory_id} ``` > 重要说明:当 `directory_id` 为 0 时,表示获取根目录的虚拟详情 响应: ```json { "code": 200, "message": "获取目录详情成功", "data": { "id": 1, "name": "照片集", "parent_id": 0, "user_id": 1, "path": "/照片集", "create_time": "2024-05-15T12:00:00Z", "update_time": "2024-05-15T12:00:00Z", "is_deleted": false }, "timestamp": "2024-05-15T12:20:00Z" } ``` 对于根目录(ID=0)的响应示例: ```json { "code": 200, "message": "获取根目录详情成功", "data": { "id": 0, "name": "根目录", "parent_id": null, "user_id": 1, "path": "/", "create_time": "2024-05-15T12:00:00Z", "update_time": "2024-05-15T12:00:00Z", "is_deleted": false }, "timestamp": "2024-05-15T12:20:00Z" } ``` #### 更新目录 ``` PUT /api/directories/{directory_id} ``` 请求体: ```json { "name": "新照片集", "parent_id": 2 // 更新父目录ID,0表示移动到根目录 } ``` 响应: ```json { "code": 200, "message": "目录更新成功", "data": { "id": 1, "name": "新照片集", "parent_id": 2, "user_id": 1, "path": "/文档/新照片集", "create_time": "2024-05-15T12:00:00Z", "update_time": "2024-05-15T12:25:00Z", "is_deleted": false }, "timestamp": "2024-05-15T12:25:00Z" } ``` #### 批量删除目录和文件 ``` POST /api/directories/batch-delete ``` 请求体: ```json { "directory_ids": [1, 2, 3], "file_ids": [4, 5, 6], "permanent": false, // 是否永久删除,默认false "recursive": true // 是否递归删除子目录和文件,默认true } ``` > 注意:此接口支持同时删除多个目录和文件。设置`recursive=true`时,会递归删除目录中的所有子目录和文件。如果只需要删除文件或只需要删除目录,可以只提供相应的参数。 响应: ```json { "code": 200, "message": "成功删除 6 个项目(3 个目录,3 个文件)", "data": { "directories": { "success_count": 3, "failed_count": 0, "failed_directories": [], "affected_files_count": 15 // 被递归删除的文件数量 }, "files": { "success_count": 3, "failed_count": 0, "failed_files": [] }, "total_success_count": 6, "total_failed_count": 0, "is_permanent": false }, "timestamp": "2024-05-15T12:30:00Z" } ``` > 注意:此接口将替代原有的单个目录删除接口(`DELETE /api/directories/{directory_id}`)和文件批量删除接口(`POST /api/files/batch-delete`)。推荐使用此接口进行所有删除操作。 #### 将文件和目录移动到指定目录 ``` POST /api/directories/move-items ``` 请求体: ```json { "file_ids": [1, 2, 3], "directory_ids": [4, 5], "target_directory_id": 1 // 目标目录ID,0表示移动到根目录 } ``` > 注意:如果只需要移动文件,可以只提供 `file_ids` 参数;如果只需要移动目录,可以只提供 `directory_ids` 参数。 响应: ```json { "code": 200, "message": "成功移动 5 个项目(3 个文件,2 个目录)", "data": { "files": { "success_count": 3, "failed_count": 0, "failed_files": [] }, "directories": { "success_count": 2, "failed_count": 0, "failed_directories": [] }, "total_success_count": 5, "total_failed_count": 0 }, "timestamp": "2024-05-15T12:40:00Z" } ``` #### 获取目录下的文件 ``` GET /api/directories/{directory_id}/files ``` > 重要说明:当 `directory_id` 为 0 时,表示获取根目录下的文件 响应: ```json { "code": 200, "message": "获取目录文件成功", "data": { "items": [ { "id": 2, "user_id": 1, "file_name": "目录中的文件.jpg", "file_path": "1/photo/2024/05/15/目录中的文件_b2c3d4e5.jpg", "file_type": "photo", "file_size": 2048, "hash": "b2c3d4e5f6g7h8i9j0...", "upload_time": "2024-05-15T12:30:00Z", "create_time": "2024-05-15T12:00:00Z", "extension": "jpg", "mime_type": "image/jpeg", "remark": null, "is_deleted": false, "directory_id": 1 } ] }, "timestamp": "2024-05-15T12:45:00Z" } ``` ### 备份管理 备份管理API提供文件备份和恢复功能,支持增量备份和全量备份,可以设置定时备份计划。 #### 创建备份任务 ``` POST /api/backups ``` 请求体: ```json { "name": "全量备份", "type": "full", // full: 全量备份, incremental: 增量备份 "directory_id": 0, // 0表示备份根目录下所有文件,其他值表示备份指定目录 "description": "每周全量备份" // 可选 } ``` 响应: ```json { "code": 200, "message": "备份任务创建成功", "data": { "id": 1, "name": "全量备份", "type": "full", "directory_id": 0, "description": "每周全量备份", "create_time": "2024-05-15T12:00:00Z", "update_time": "2024-05-15T12:00:00Z", "status": "created", "is_deleted": false }, "timestamp": "2024-05-15T12:00:00Z" } ``` #### 执行备份任务 ``` POST /api/backups/{backup_id}/execute ``` 响应: ```json { "code": 200, "message": "备份任务执行已开始", "data": { "task_id": "550e8400-e29b-41d4-a716-446655440000", "backup_id": 1, "status": "running", "start_time": "2024-05-15T12:05:00Z", "estimated_completion_time": "2024-05-15T12:10:00Z" }, "timestamp": "2024-05-15T12:05:00Z" } ``` #### 获取备份任务列表 ``` GET /api/backups ``` 参数: - page: 页码(默认1) - page_size: 每页数量(默认20) - type: 备份类型(full/incremental,可选) - status: 任务状态(created/running/completed/failed,可选) - directory_id: 目录ID(可选) 响应: ```json { "code": 200, "message": "获取备份任务列表成功", "data": { "total": 10, "page": 1, "page_size": 20, "items": [ { "id": 1, "name": "全量备份", "type": "full", "directory_id": 0, "description": "每周全量备份", "create_time": "2024-05-15T12:00:00Z", "update_time": "2024-05-15T12:30:00Z", "status": "completed", "last_execution_time": "2024-05-15T12:05:00Z", "completion_time": "2024-05-15T12:10:00Z", "total_files": 100, "backed_up_files": 100, "total_size": 1073741824, "is_deleted": false }, { "id": 2, "name": "增量备份", "type": "incremental", "directory_id": 1, "description": "每日增量备份", "create_time": "2024-05-16T12:00:00Z", "update_time": "2024-05-16T12:20:00Z", "status": "completed", "last_execution_time": "2024-05-16T12:05:00Z", "completion_time": "2024-05-16T12:08:00Z", "total_files": 10, "backed_up_files": 10, "total_size": 10485760, "is_deleted": false } ] }, "timestamp": "2024-05-16T15:00:00Z" } ``` #### 获取备份任务详情 ``` GET /api/backups/{backup_id} ``` 响应: ```json { "code": 200, "message": "获取备份任务详情成功", "data": { "id": 1, "name": "全量备份", "type": "full", "directory_id": 0, "directory_name": "根目录", "description": "每周全量备份", "create_time": "2024-05-15T12:00:00Z", "update_time": "2024-05-15T12:30:00Z", "status": "completed", "last_execution_time": "2024-05-15T12:05:00Z", "completion_time": "2024-05-15T12:10:00Z", "total_files": 100, "backed_up_files": 100, "total_size": 1073741824, "backup_path": "backups/20240515/full_backup_1", "is_deleted": false, "executions": [ { "id": 1, "backup_id": 1, "status": "completed", "start_time": "2024-05-15T12:05:00Z", "end_time": "2024-05-15T12:10:00Z", "files_count": 100, "total_size": 1073741824, "error_message": null } ] }, "timestamp": "2024-05-16T15:10:00Z" } ``` #### 获取备份文件列表 ``` GET /api/backups/{backup_id}/files ``` 参数: - page: 页码(默认1) - page_size: 每页数量(默认20) - file_type: 文件类型 (photo/video/audio/document/other,可选) - keyword: 搜索关键词(可选) 响应: ```json { "code": 200, "message": "获取备份文件列表成功", "data": { "total": 100, "page": 1, "page_size": 20, "items": [ { "id": 1, "file_name": "example.jpg", "file_path": "1/photo/2024/05/15/example_12345678.jpg", "file_type": "photo", "file_size": 1024, "create_time": "2024-05-15T10:00:00Z", "backed_up_time": "2024-05-15T12:05:00Z", "directory_id": 0, "directory_path": "/" } ] }, "timestamp": "2024-05-16T15:20:00Z" } ``` #### 恢复备份 ``` POST /api/backups/{backup_id}/restore ``` 请求体: ```json { "file_ids": [1, 2, 3], // 可选,不提供则恢复所有文件 "restore_path": "restored_files", // 可选,恢复到指定目录,不提供则恢复到原位置 "overwrite": false // 可选,是否覆盖同名文件,默认false } ``` 响应: ```json { "code": 200, "message": "恢复任务已开始", "data": { "task_id": "550e8400-e29b-41d4-a716-446655440001", "backup_id": 1, "status": "running", "files_to_restore": 3, "restore_path": "restored_files", "overwrite": false, "start_time": "2024-05-16T15:30:00Z", "estimated_completion_time": "2024-05-16T15:35:00Z" }, "timestamp": "2024-05-16T15:30:00Z" } ``` #### 获取恢复任务状态 ``` GET /api/backups/restore-tasks/{task_id} ``` 响应: ```json { "code": 200, "message": "获取恢复任务状态成功", "data": { "task_id": "550e8400-e29b-41d4-a716-446655440001", "backup_id": 1, "status": "completed", "start_time": "2024-05-16T15:30:00Z", "completion_time": "2024-05-16T15:33:00Z", "total_files": 3, "restored_files": 3, "failed_files": 0, "restore_path": "restored_files", "failed_details": [] }, "timestamp": "2024-05-16T15:40:00Z" } ``` #### 删除备份任务 ``` DELETE /api/backups/{backup_id} ``` 参数: - delete_files: 是否同时删除备份文件(默认false) 响应: ```json { "code": 200, "message": "备份任务删除成功", "data": { "backup_files_deleted": false }, "timestamp": "2024-05-16T15:50:00Z" } ``` #### 创建定时备份计划 ``` POST /api/backup-schedules ``` 请求体: ```json { "name": "每日增量备份", "backup_type": "incremental", "directory_id": 0, "schedule_type": "daily", // daily, weekly, monthly "time": "02:00:00", // 执行时间 (HH:MM:SS) "day_of_week": null, // 0-6 (周一到周日),weekly时必填 "day_of_month": null, // 1-31,monthly时必填 "description": "每天凌晨2点执行增量备份", "enabled": true } ``` 响应: ```json { "code": 200, "message": "备份计划创建成功", "data": { "id": 1, "name": "每日增量备份", "backup_type": "incremental", "directory_id": 0, "schedule_type": "daily", "time": "02:00:00", "day_of_week": null, "day_of_month": null, "description": "每天凌晨2点执行增量备份", "enabled": true, "next_execution": "2024-05-17T02:00:00Z", "create_time": "2024-05-16T16:00:00Z", "update_time": "2024-05-16T16:00:00Z" }, "timestamp": "2024-05-16T16:00:00Z" } ``` #### 获取备份计划列表 ``` GET /api/backup-schedules ``` 参数: - page: 页码(默认1) - page_size: 每页数量(默认20) - enabled: 是否启用(true/false,可选) 响应: ```json { "code": 200, "message": "获取备份计划列表成功", "data": { "total": 3, "page": 1, "page_size": 20, "items": [ { "id": 1, "name": "每日增量备份", "backup_type": "incremental", "directory_id": 0, "directory_name": "根目录", "schedule_type": "daily", "time": "02:00:00", "day_of_week": null, "day_of_month": null, "description": "每天凌晨2点执行增量备份", "enabled": true, "next_execution": "2024-05-17T02:00:00Z", "last_execution": "2024-05-16T02:00:00Z", "last_execution_status": "completed", "create_time": "2024-05-15T16:00:00Z", "update_time": "2024-05-15T16:00:00Z" }, { "id": 2, "name": "每周全量备份", "backup_type": "full", "directory_id": 0, "directory_name": "根目录", "schedule_type": "weekly", "time": "03:00:00", "day_of_week": 0, "day_of_month": null, "description": "每周一凌晨3点执行全量备份", "enabled": true, "next_execution": "2024-05-20T03:00:00Z", "last_execution": "2024-05-13T03:00:00Z", "last_execution_status": "completed", "create_time": "2024-05-01T16:00:00Z", "update_time": "2024-05-01T16:00:00Z" } ] }, "timestamp": "2024-05-16T16:10:00Z" } ``` #### 更新备份计划 ``` PUT /api/backup-schedules/{schedule_id} ``` 请求体: ```json { "name": "更新后的备份计划", "backup_type": "full", "directory_id": 1, "schedule_type": "weekly", "time": "04:00:00", "day_of_week": 6, "day_of_month": null, "description": "每周日凌晨4点执行全量备份", "enabled": true } ``` 响应: ```json { "code": 200, "message": "备份计划更新成功", "data": { "id": 1, "name": "更新后的备份计划", "backup_type": "full", "directory_id": 1, "schedule_type": "weekly", "time": "04:00:00", "day_of_week": 6, "day_of_month": null, "description": "每周日凌晨4点执行全量备份", "enabled": true, "next_execution": "2024-05-19T04:00:00Z", "create_time": "2024-05-15T16:00:00Z", "update_time": "2024-05-16T16:20:00Z" }, "timestamp": "2024-05-16T16:20:00Z" } ``` #### 删除备份计划 ``` DELETE /api/backup-schedules/{schedule_id} ``` 响应: ```json { "code": 200, "message": "备份计划删除成功", "data": null, "timestamp": "2024-05-16T16:30:00Z" } ``` #### 手动触发备份计划 ``` POST /api/backup-schedules/{schedule_id}/execute ``` 响应: ```json { "code": 200, "message": "备份计划执行已开始", "data": { "task_id": "550e8400-e29b-41d4-a716-446655440002", "schedule_id": 1, "backup_id": 10, "status": "running", "start_time": "2024-05-16T16:40:00Z", "estimated_completion_time": "2024-05-16T16:45:00Z" }, "timestamp": "2024-05-16T16:40:00Z" } ``` ## 错误码说明 - 200: 成功 - 400: 请求参数错误 - 401: 未认证 - 403: 无权限访问 - 404: 资源不存在 - 500: 服务器内部错误 ## 认证说明 所有需要认证的接口都需要在请求头中携带 Token: ``` Authorization: Bearer ``` Token 可以通过以下方式获取: 1. 调用登录接口获取 2. 使用刷新令牌获取新的访问令牌 ## 断点上传说明 对于大文件上传,推荐使用断点上传功能,具体流程如下: 1. 客户端计算文件大小,确定分片大小(推荐 5MB 或更大) 2. 调用初始化接口,获取 task_id 和其他上传信息 3. 并发上传多个分片(推荐 3-5 个并发请求) 4. 定期查询上传状态,显示进度 5. 所有分片上传完成后,调用完成接口 6. 如果上传中断,可以在用户重新连接后查询状态,继续上传未完成的分片 ## 使用示例 ### Python 示例 ```python import requests # 登录获取token response = requests.post( "http://localhost:8000/auth/login", data={ "username": "your_username", "password": "your_password" } ) token_data = response.json()["data"] access_token = token_data["access_token"] # 设置认证头 headers = { "Authorization": f"Bearer {access_token}" } # 获取文件列表 response = requests.get( "http://localhost:8000/api/files", headers=headers, params={ "page": 1, "page_size": 20 } ) # 上传文件 with open("example.jpg", "rb") as f: response = requests.post( "http://localhost:8000/api/upload", headers=headers, files={"file": f} ) ``` ## 目录结构 ``` file-service/ ├── app/ │ ├── __init__.py │ ├── main.py # FastAPI 应用入口 │ │ ├── __init__.py │ │ ├── core/ # 核心配置 │ │ │ ├── __init__.py │ │ │ ├── config.py # 应用配置 │ │ │ └── logging_config.py # 日志配置 │ │ ├── database/ │ │ │ ├── __init__.py │ │ │ ├── database.py # 数据库连接 │ │ │ └── models.py # 数据模型 │ │ ├── routers/ │ │ │ ├── __init__.py │ │ │ ├── auth_router.py # 认证路由 │ │ │ ├── upload_router.py # 文件上传路由 │ │ │ ├── file_router.py # 文件管理路由 │ │ │ └── chunk_upload_router.py # 断点上传路由 │ │ ├── services/ │ │ │ ├── __init__.py │ │ │ ├── auth_service.py # 认证服务 │ │ │ ├── file_service.py # 文件服务 │ │ │ ├── user_service.py # 用户服务 │ │ │ └── upload_chunk_service.py # 断点上传服务 │ │ ├── schemas/ │ │ │ ├── __init__.py │ │ │ ├── file_schema.py # 文件模型序列化 │ │ │ └── chunk_schema.py # 断点上传模型序列化 │ │ ├── tasks/ │ │ │ ├── __init__.py │ │ │ └── cleanup_task.py # 清理过期任务 │ │ └── utils/ │ │ ├── __init__.py │ │ ├── minio_client.py # MinIO客户端 │ │ ├── file_utils.py # 文件工具 │ │ └── response_utils.py # 响应工具 │ ├── tests/ # 测试目录 │ ├── .env # 环境变量 │ ├── .env.example # 环境变量示例 │ ├── .gitignore │ └── requirements.txt # 依赖包 ``` ## 依赖要求 - Python 3.8+ - FastAPI 0.100.0+ - SQLAlchemy 1.4+ - MinIO 7.2.0 - Pillow 10.0.0+ - python-multipart - python-jose[cryptography] - passlib[bcrypt] - python-dotenv - uvicorn - pydantic-settings ## 环境配置 系统使用 `.env` 文件进行配置管理。在项目根目录创建 `.env` 文件,配置以下必要参数: ```env # 数据库配置 DATABASE_URL=mysql+pymysql://root:password@localhost:3306/file_service # MinIO配置 MINIO_ENDPOINT=http://localhost:9000/ MINIO_ACCESS_KEY=minioadmin MINIO_SECRET_KEY=minioadmin MINIO_BUCKET_NAME=user-uploads MINIO_SECURE=False # JWT配置 JWT_SECRET_KEY=your-secret-key JWT_ALGORITHM=HS256 JWT_ACCESS_TOKEN_EXPIRE_MINUTES=10080 ``` ## 开发环境搭建 1. 安装依赖: ```bash pip install -r requirements.txt ``` 2. 配置数据库和MinIO: ```bash # 修改 .env 文件中的配置 ``` 3. 运行服务: ```bash uvicorn app.main:app --reload ``` ## API 文档 启动服务后,访问以下地址查看 Swagger UI 文档: ``` http://localhost:8000/docs ```