为 data_pipeline/training_data/
目录设计一套完整的文件管理API系统,提供目录浏览、文件操作、安全管理等功能。
需求 | 描述 | 优先级 |
---|---|---|
递归遍历 | 支持整个training_data目录的递归遍历 | 🟢 高 |
层级控制 | 可指定遍历深度,避免性能问题 | 🟡 中 |
筛选功能 | 按文件类型、大小、时间等条件筛选 | 🟡 中 |
排序功能 | 按名称、时间、大小等排序 | 🟡 中 |
需求 | 描述 | 优先级 |
---|---|---|
基本信息 | 文件名、大小、类型、修改时间等 | 🟢 高 |
详细属性 | 权限、创建时间、文件哈希等 | 🟡 中 |
分页支持 | 大目录的分页展示 | 🟡 中 |
搜索功能 | 按文件名模糊搜索 | 🟡 中 |
需求 | 描述 | 优先级 |
---|---|---|
单文件下载 | 支持各种文件类型下载 | 🟢 高 |
流式下载 | 大文件的流式传输 | 🟡 中 |
批量下载 | 多文件打包下载 | 🔴 低 |
断点续传 | 大文件下载中断恢复 | 🔴 低 |
需求 | 描述 | 优先级 |
---|---|---|
单文件删除 | 删除指定文件 | 🟢 高 |
批量删除 | 删除多个文件 | 🟡 中 |
安全确认 | 删除前的确认机制 | 🟢 高 |
回收站 | 软删除,可恢复 | 🔴 低 |
需求 | 描述 | 优先级 |
---|---|---|
单文件上传 | 支持各种文件类型上传 | 🟢 高 |
同名覆盖 | 自动覆盖同名文件 | 🟢 高 |
分片上传 | 大文件分片上传 | 🟡 中 |
进度跟踪 | 上传进度实时反馈 | 🟡 中 |
基础路径: /api/v0/training_data/files
认证方式: 继承现有系统认证
响应格式: JSON
错误处理: 标准HTTP状态码 + 详细错误信息
GET /api/v0/training_data/files/tree
查询参数:
max_depth
: 最大遍历深度 (默认: 3)include_files
: 是否包含文件 (默认: true)file_types
: 筛选文件类型 (如: ddl,md,json)响应示例:
{
"success": true,
"data": {
"directory": "training_data",
"path": "./data_pipeline/training_data",
"children": [
{
"name": "vector_bak",
"type": "directory",
"path": "./data_pipeline/training_data/vector_bak",
"file_count": 4,
"size": "1.6MB",
"children": [
{
"name": "langchain_pg_collection_20250722_132518.csv",
"type": "file",
"path": "./data_pipeline/training_data/vector_bak/langchain_pg_collection_20250722_132518.csv",
"size": "209B",
"modified_at": "2025-07-22T13:25:18Z",
"file_type": "csv"
}
]
}
]
},
"meta": {
"total_directories": 15,
"total_files": 89,
"total_size": "25.4MB",
"scan_time": "0.234s"
}
}
GET /api/v0/training_data/files/list
查询参数:
path
: 相对路径 (默认: ".")page
: 页码 (默认: 1)page_size
: 每页大小 (默认: 50)sort_by
: 排序字段 (name|size|modified_at)sort_order
: 排序方向 (asc|desc)search
: 文件名搜索关键词响应示例:
{
"success": true,
"data": {
"current_path": "./data_pipeline/training_data/task_20250721_213627",
"items": [
{
"name": "bss_business_day_data.ddl",
"type": "file",
"size": 1024,
"size_formatted": "1.0 KB",
"modified_at": "2025-07-21T21:36:27Z",
"created_at": "2025-07-21T21:36:27Z",
"file_type": "ddl",
"permissions": "rw-r--r--"
},
{
"name": "vector_bak",
"type": "directory",
"size": 819200,
"size_formatted": "800 KB",
"modified_at": "2025-07-22T01:03:18Z",
"file_count": 4
}
]
},
"pagination": {
"page": 1,
"page_size": 50,
"total": 25,
"total_pages": 1,
"has_next": false,
"has_prev": false
}
}
GET /api/v0/training_data/files/download
查询参数:
path
: 文件相对路径 (必需)inline
: 是否内联显示 (默认: false)响应: 文件流 Headers:
Content-Type
: 根据文件类型自动设置Content-Disposition
: attachment; filename="文件名"Content-Length
: 文件大小GET /api/v0/training_data/files/preview
查询参数:
path
: 文件相对路径 (必需)lines
: 预览行数 (默认: 100)encoding
: 文件编码 (默认: utf-8)响应示例:
{
"success": true,
"data": {
"file_path": "./data_pipeline/training_data/task_xxx/metadata.txt",
"file_size": 2048,
"content_preview": "业务日数据表...",
"total_lines": 45,
"preview_lines": 100,
"encoding": "utf-8",
"is_text_file": true
}
}
DELETE /api/v0/training_data/files/delete
请求体:
{
"path": "./data_pipeline/training_data/task_xxx/old_file.json",
"confirm": true
}
响应示例:
{
"success": true,
"message": "文件删除成功",
"data": {
"deleted_file": {
"path": "./data_pipeline/training_data/task_xxx/old_file.json",
"name": "old_file.json",
"size": 1024,
"deleted_at": "2025-07-22T15:30:00Z"
}
}
}
POST /api/v0/training_data/files/batch_delete
请求体:
{
"paths": [
"./data_pipeline/training_data/task_xxx/file1.json",
"./data_pipeline/training_data/task_xxx/file2.ddl"
],
"confirm": true
}
响应示例:
{
"success": true,
"data": {
"deleted_files": [
{
"path": "./data_pipeline/training_data/task_xxx/file1.json",
"success": true
}
],
"failed_files": [
{
"path": "./data_pipeline/training_data/task_xxx/file2.ddl",
"success": false,
"error": "文件不存在"
}
],
"summary": {
"total": 2,
"success": 1,
"failed": 1
}
}
}
POST /api/v0/training_data/files/upload
请求: multipart/form-data
file
: 文件数据 (必需)path
: 目标目录相对路径 (默认: ".")filename
: 自定义文件名 (可选)overwrite
: 是否覆盖同名文件 (默认: true)响应示例:
{
"success": true,
"message": "文件上传成功",
"data": {
"uploaded_file": {
"original_name": "table_list.txt",
"saved_name": "table_list.txt",
"path": "./data_pipeline/training_data/task_xxx/table_list.txt",
"size": 256,
"size_formatted": "256 B",
"uploaded_at": "2025-07-22T15:45:00Z",
"file_type": "text",
"overwrite_occurred": true
},
"backup_info": {
"backup_created": true,
"backup_path": "./data_pipeline/training_data/task_xxx/table_list.txt.bak1",
"backup_created_at": "2025-07-22T15:45:00Z"
}
}
}
POST /api/v0/training_data/files/batch_upload
请求: multipart/form-data
files[]
: 多个文件 (必需)path
: 目标目录相对路径 (默认: ".")overwrite
: 是否覆盖同名文件 (默认: true)GET /api/v0/training_data/files/stats
查询参数:
path
: 目录相对路径 (默认: ".")recursive
: 是否递归统计 (默认: true)响应示例:
{
"success": true,
"data": {
"directory_stats": {
"path": "./data_pipeline/training_data",
"total_directories": 12,
"total_files": 87,
"total_size": 26542080,
"total_size_formatted": "25.3 MB",
"file_type_breakdown": {
"ddl": {"count": 18, "size": 45120},
"md": {"count": 18, "size": 234560},
"json": {"count": 15, "size": 1024000},
"csv": {"count": 8, "size": 25000000},
"txt": {"count": 12, "size": 15360},
"log": {"count": 16, "size": 223040}
},
"largest_files": [
{
"name": "langchain_pg_embedding_20250722_132518.csv",
"path": "./data_pipeline/training_data/vector_bak/langchain_pg_embedding_20250722_132518.csv",
"size": 838860,
"size_formatted": "819 KB"
}
]
}
}
}
GET /api/v0/training_data/files/search
查询参数:
query
: 搜索关键词 (必需)file_types
: 文件类型筛选 (可选)max_results
: 最大结果数 (默认: 50)search_type
: 搜索类型 (name|content) (默认: name)响应示例:
{
"success": true,
"data": {
"search_query": "business_day",
"search_type": "name",
"results": [
{
"name": "bss_business_day_data.ddl",
"path": "./data_pipeline/training_data/task_20250721_213627/bss_business_day_data.ddl",
"size": 1024,
"modified_at": "2025-07-21T21:36:27Z",
"file_type": "ddl",
"match_score": 0.95
}
],
"summary": {
"total_results": 3,
"search_time": "0.045s"
}
}
}
def validate_path(relative_path: str) -> bool:
"""验证路径安全性"""
# 1. 禁止绝对路径
if os.path.isabs(relative_path):
return False
# 2. 禁止路径遍历
if '..' in relative_path:
return False
# 3. 解析后验证在允许范围内
full_path = os.path.join(TRAINING_DATA_ROOT, relative_path)
real_path = os.path.realpath(full_path)
return real_path.startswith(os.path.realpath(TRAINING_DATA_ROOT))
.ddl
, .sql
, .md
, .json
, .txt
, .csv
, .log
.exe
, .bat
, .sh
, .py
(可执行文件)操作 | 权限要求 | 说明 |
---|---|---|
目录浏览 | 只读 | 所有用户 |
文件下载 | 只读 | 所有用户 |
文件上传 | 读写 | 需要认证 |
文件删除 | 读写 | 需要认证 + 确认 |
{
"success": false,
"error": {
"code": "FILE_NOT_FOUND",
"message": "指定的文件不存在",
"details": {
"path": "./data_pipeline/training_data/nonexistent.txt",
"timestamp": "2025-07-22T15:30:00Z"
}
}
}
错误代码 | HTTP状态 | 说明 |
---|---|---|
INVALID_PATH |
400 | 路径格式错误或不安全 |
FILE_NOT_FOUND |
404 | 文件不存在 |
DIRECTORY_NOT_FOUND |
404 | 目录不存在 |
PERMISSION_DENIED |
403 | 权限不足 |
FILE_TOO_LARGE |
413 | 文件超过大小限制 |
UNSUPPORTED_FILE_TYPE |
415 | 不支持的文件类型 |
DISK_SPACE_FULL |
507 | 磁盘空间不足 |
┌─────────────────────────────────────────────────────────────┐
│ Training Data File Management API │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌──────┐ │
│ │ 目录API │ │ 文件API │ │ 上传API │ │ 统计 │ │
│ │ tree/list │ │download/del │ │upload/batch │ │ API │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └──────┘ │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ TrainingDataFileManager (核心管理器) │ │
│ │ • 路径安全验证 • 文件操作封装 • 错误处理 • 日志记录 │ │
│ └─────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌─────────────────────┐ │
│ │ 路径管理 │ │ 文件操作 │ │ 安全策略 │ │
│ │ • 路径解析 │ │ • 读写操作 │ │ • 权限验证 │ │
│ │ • 安全检查 │ │ • 元数据 │ │ • 类型检查 │ │
│ │ • 目录遍历 │ │ • 流式处理 │ │ • 大小限制 │ │
│ └──────────────┘ └──────────────┘ └─────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ 现有 data_pipeline 基础设施 │
│ • unified_api.py 路由 • 日志系统 • 配置管理 │
└─────────────────────────────────────────────────────────────┘
class TrainingDataFileManager:
"""Training Data 文件管理器"""
def __init__(self, base_path: str = "data_pipeline/training_data"):
self.base_path = Path(base_path)
self.logger = get_logger("TrainingDataFileManager")
# 核心方法
def get_directory_tree(self, max_depth: int = 3) -> Dict
def list_directory_contents(self, path: str, **kwargs) -> Dict
def download_file(self, path: str) -> FileResponse
def upload_file(self, file_data, target_path: str) -> Dict
def delete_file(self, path: str) -> Dict
def get_file_stats(self, path: str) -> Dict
def search_files(self, query: str, **kwargs) -> Dict
# 安全验证
def validate_path(self, path: str) -> bool
def check_file_type(self, filename: str) -> bool
def check_file_size(self, size: int) -> bool
# data_pipeline/config.py
TRAINING_DATA_FILE_MANAGEMENT = {
"enabled": True,
"max_file_size": 100 * 1024 * 1024, # 100MB
"allowed_extensions": [".ddl", ".sql", ".md", ".json", ".txt", ".csv", ".log"],
"max_tree_depth": 5,
"max_search_results": 100,
"cache_enabled": True,
"cache_ttl": 300, # 5分钟
"upload_chunk_size": 1024 * 1024, # 1MB
}
// 获取目录树
const getDirectoryTree = async () => {
const response = await fetch('/api/v0/training_data/files/tree?max_depth=3');
const data = await response.json();
return data;
};
// 上传文件
const uploadFile = async (file, targetPath = '.') => {
const formData = new FormData();
formData.append('file', file);
formData.append('path', targetPath);
formData.append('overwrite', 'true');
const response = await fetch('/api/v0/training_data/files/upload', {
method: 'POST',
body: formData
});
return await response.json();
};
// 删除文件
const deleteFile = async (filePath) => {
const response = await fetch('/api/v0/training_data/files/delete', {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ path: filePath, confirm: true })
});
return await response.json();
};
# 获取目录列表
curl "http://localhost:8084/api/v0/training_data/files/list?path=task_20250721_213627"
# 下载文件
curl -O "http://localhost:8084/api/v0/training_data/files/download?path=task_xxx/metadata.txt"
# 上传文件
curl -X POST -F "file=@local_file.txt" -F "path=task_xxx" \
"http://localhost:8084/api/v0/training_data/files/upload"
# 删除文件
curl -X DELETE -H "Content-Type: application/json" \
-d '{"path":"task_xxx/old_file.json","confirm":true}' \
"http://localhost:8084/api/v0/training_data/files/delete"
# 搜索文件
curl "http://localhost:8084/api/v0/training_data/files/search?query=business&file_types=ddl,md"
这个文件管理系统API设计方案提供了:
这个设计方案可以作为后续开发的详细指导,确保实现一个功能完整、安全可靠、易于使用的文件管理系统。
文档版本: v1.0
创建日期: 2025-07-22
作者: AI Assistant
审核状态: 待审核