Large File Upload SDK - Support chunked upload, resumable transfer, and Token authentication
Project description
File Upload Server
星河启智二期用于上传大文件的服务器 - 基于 FastAPI 构建,支持分片上传和断点续传
功能特性
- ✅ 分片上传: 支持大文件分片上传,提高上传成功率
- ✅ 断点续传: 网络中断后可继续上传,无需重新开始
- ✅ MD5校验: 可选的文件和分片MD5校验,确保数据完整性
- ✅ 并发控制: 支持多文件并发上传
- ✅ 自动清理: 自动清理过期的临时文件
- ✅ Token认证: 类似HuggingFace的Token认证机制,安全便捷
- ✅ 权限控制: 支持用户角色和数据集访问权限管理
- ✅ 使用限制: 支持文件大小和每日上传次数限制
- ✅ 上传记录: 自动保存上传记录到数据库,支持查询和统计
- ✅ RESTful API: 提供完整的REST API接口
- ✅ 在线文档: 自动生成的API文档
- ✅ Docker支持: 支持容器化部署
技术栈
- 后端框架: FastAPI 0.104+
- 异步处理: asyncio + aiofiles
- 数据验证: Pydantic
- ASGI服务器: Uvicorn
- 容器化: Docker
快速开始
环境要求
- Python 3.11+
- 或者 Docker
本地开发
- 克隆项目
git clone <repository-url>
cd file-upload-server
- 安装依赖
pip install -r requirements.txt
- 配置环境变量
cp env.example .env
# 编辑 .env 文件,根据环境修改 UPLOAD_BASE_DIR
- 启动服务
python main.py
服务将在 http://localhost:8000 启动
Docker部署
- 构建镜像
docker build -t file-upload-server .
- 运行容器
# Staging环境(使用默认配置)
docker run -d \
--name file-upload-server \
-p 8000:8000 \
-v /cpfs-nfs/sais/data-plaza-svc:/cpfs-nfs/sais/data-plaza-svc \
file-upload-server
# Production环境(只需覆盖UPLOAD_BASE_DIR)
docker run -d \
--name file-upload-server \
-p 8000:8000 \
-v /normal-cpfs-datasets:/normal-cpfs-datasets \
-v /normal-cpfs-datasets-temp:/normal-cpfs-datasets-temp \
-e UPLOAD_BASE_DIR=/normal-cpfs-datasets \
-e TEMP_DIR=/normal-cpfs-datasets-temp \
file-upload-server
API 接口
服务启动后访问 http://localhost:8000/docs 查看完整的API文档
主要接口
| 接口 | 方法 | 说明 |
|---|---|---|
/ |
GET | 服务信息 |
/health |
GET | 健康检查 |
/api/token/generate |
POST | 生成访问令牌 |
/api/token/verify |
POST | 验证令牌有效性 |
/api/token/revoke |
DELETE | 撤销访问令牌 |
/api/upload/check |
POST | 检查文件状态,支持断点续传 |
/api/upload/chunk |
POST | 上传文件分片 |
/api/upload/merge |
POST | 合并分片完成上传 |
/api/upload/status/{file_id} |
GET | 获取上传状态 |
/api/upload/{file_id} |
DELETE | 取消上传 |
/api/upload/records |
GET | 查询上传记录(支持分页和筛选) |
/api/upload/records/stats |
GET | 获取上传统计信息 |
/api/download/{filename} |
GET | 下载文件 |
使用示例
Python SDK
安装SDK
pip install large-file-upload-sdk
用法(Token认证 - 推荐)
import file_upload_sdk as api # 注意:包名是large-file-upload-sdk,但导入时使用file_upload_sdk
# 方式1:使用用户信息自动获取Token
api.init_sdk(
base_url="https://file-upload-server.ai4s.com.cn/",
user_id=12345,
user_name="张三"
)
# 方式2:直接使用已有的Token
api.init_sdk(
base_url="https://file-upload-server.ai4s.com.cn/",
access_token="hf_AbCdEfGhIjKlMnOpQrStUvWxYz1234567890"
)
# 上传文件
result = api.upload_file(
file_path="/path/to/local/your_file.suffix",
dataset_id="my-dataset",
file_name="your_file.suffix"
)
if result['success']:
print(f"上传成功!文件URL: {result['file_url']}")
else:
print(f"上传失败: {result['error']}")
兼容旧版本(API Key认证)
import file_upload_sdk as api
# 使用API Key(兼容旧版本)
api.init_sdk(
base_url="http://localhost:8000",
api_key="ak_12345_xxx_yyy"
)
# 或者通过user_id自动申请API Key
api.init_sdk(
base_url="http://localhost:8000",
user_id=12345
)
带进度显示的用法
import file_upload_sdk as api
api.init_sdk("http://localhost:8000")
def show_progress(progress):
print(f"\r上传进度: {progress:.1f}%", end="", flush=True)
result = api.upload_file(
file_path="/path/to/large_file.zip",
file_name="uploaded_file.zip",
progress_callback=show_progress
)
面向对象的用法
from file_upload_sdk import FileUploadSDK
# Token认证方式
sdk = FileUploadSDK(
base_url="http://localhost:8000",
user_id=12345,
user_name="张三",
chunk_size=5 * 1024 * 1024, # 5MB分片
retry_times=5
)
# 或者直接使用Token
sdk = FileUploadSDK(
base_url="http://localhost:8000",
access_token="hf_AbCdEfGhIjKlMnOpQrStUvWxYz1234567890",
chunk_size=5 * 1024 * 1024,
retry_times=5
)
result = sdk.upload_file(
file_path="/path/to/your_file.suffix",
dataset_id="my-dataset",
file_name="your_file.suffix",
enable_md5_check=True
)
断点续传示例
import file_upload_sdk as api
# 使用Token认证
api.init_sdk(
base_url="http://localhost:8000",
user_id=12345,
user_name="张三"
)
# 使用自定义文件ID进行断点续传
file_id = "my_unique_file_id"
result = api.upload_file(
file_path="/path/to/large_file.zip",
dataset_id="my-dataset",
file_name="large_file.zip",
custom_file_id=file_id
)
# 如果上传中断,再次调用相同的代码即可继续上传
cURL 使用示例
0. 获取访问令牌(首次使用)
curl -X POST "http://localhost:8000/api/token/generate" \
-H "Content-Type: application/json" \
-d '{
"user_id": "12345",
"user_name": "张三",
"role": "user",
"max_file_size": 10737418240,
"daily_upload_limit": 100
}'
响应示例:
{
"access_token": "hf_AbCdEfGhIjKlMnOpQrStUvWxYz1234567890",
"token_type": "Bearer",
"user_info": {
"user_id": "12345",
"user_name": "张三",
"role": "user",
"max_file_size": 10737418240,
"daily_upload_limit": 100
}
}
1. 检查文件状态
curl -X POST "http://localhost:8000/api/upload/check" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer hf_AbCdEfGhIjKlMnOpQrStUvWxYz1234567890" \
-d '{
"file_id": "unique-file-id",
"file_name": "large-file.zip",
"file_size": 1073741824,
"total_chunks": 100,
"dataset_id": "my-dataset",
"file_md5": "d41d8cd98f00b204e9800998ecf8427e"
}'
2. 上传分片
curl -X POST "http://localhost:8000/api/upload/chunk" \
-H "Authorization: Bearer hf_AbCdEfGhIjKlMnOpQrStUvWxYz1234567890" \
-F "file_id=unique-file-id" \
-F "file_name=large-file.zip" \
-F "file_size=1073741824" \
-F "chunk_index=0" \
-F "total_chunks=100" \
-F "chunk_size=10485760" \
-F "dataset_id=my-dataset" \
-F "chunk_file=@chunk_0.bin"
3. 合并文件
curl -X POST "http://localhost:8000/api/upload/merge" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer hf_AbCdEfGhIjKlMnOpQrStUvWxYz1234567890" \
-d '{
"file_id": "unique-file-id",
"file_name": "large-file.zip",
"total_chunks": 100,
"dataset_id": "my-dataset",
"file_md5": "d41d8cd98f00b204e9800998ecf8427e"
}'
上传记录查询
系统会自动将所有成功的上传记录保存到数据库,方便用户查询历史上传记录和统计信息。
查询上传记录
接口: GET /api/upload/records
功能:
- 分页查询上传记录
- 支持按数据集ID筛选
- 支持按文件名模糊搜索
- 普通用户只能查询自己的记录,管理员可查询所有用户
示例:
# 基本查询(第一页)
curl -H "Authorization: Bearer your_token" \
"https://file-upload-server.ai4s.com.cn/api/upload/records?page=1&page_size=10"
# 按数据集筛选
curl -H "Authorization: Bearer your_token" \
"https://file-upload-server.ai4s.com.cn/api/upload/records?dataset_id=my-dataset"
# 搜索文件名
curl -H "Authorization: Bearer your_token" \
"https://file-upload-server.ai4s.com.cn/api/upload/records?file_name=report"
响应示例:
{
"code": 200,
"message": "查询成功,共 25 条记录",
"total": 25,
"page": 1,
"page_size": 10,
"records": [
{
"id": 1,
"user_id": "user_123",
"user_name": "张三",
"file_id": "abc123",
"file_name": "example.pdf",
"file_size": 10485760,
"file_md5": "d41d8cd98f00b204e9800998ecf8427e",
"file_path": "/uploads/dataset_001/example.pdf",
"dataset_id": "dataset_001",
"total_chunks": 10,
"upload_status": "completed",
"upload_started_at": "2024-01-01T10:00:00",
"upload_completed_at": "2024-01-01T10:05:00",
"created_at": "2024-01-01T10:05:00"
}
]
}
获取上传统计
接口: GET /api/upload/records/stats
功能: 获取当前用户的上传统计信息
示例:
curl -H "Authorization: Bearer your_token" \
"https://file-upload-server.ai4s.com.cn/api/upload/records/stats"
响应示例:
{
"code": 200,
"message": "统计信息获取成功",
"data": {
"total_files": 125,
"total_size": 5368709120,
"total_size_gb": 5.0,
"today_files": 10,
"today_size": 419430400,
"today_size_gb": 0.39
}
}
Python 调用示例
import requests
# 查询上传记录
def get_upload_records(token, page=1, page_size=10):
url = f"https://file-upload-server.ai4s.com.cn/api/upload/records"
headers = {"Authorization": f"Bearer {token}"}
params = {"page": page, "page_size": page_size}
response = requests.get(url, headers=headers, params=params)
return response.json()
# 获取统计信息
def get_upload_stats(token):
url = "https://file-upload-server.ai4s.com.cn/api/upload/records/stats"
headers = {"Authorization": f"Bearer {token}"}
response = requests.get(url, headers=headers)
return response.json()
# 使用示例
token = "hf_your_token_here"
records = get_upload_records(token, page=1, page_size=20)
print(f"共有 {records['total']} 条记录")
for record in records['records']:
print(f"文件: {record['file_name']}, 大小: {record['file_size']} 字节")
stats = get_upload_stats(token)
print(f"总上传: {stats['data']['total_files']} 个文件, {stats['data']['total_size_gb']} GB")
前端集成
详细的前端集成示例(React、Vue)请参考:API_UPLOAD_RECORDS.md
配置说明
主要配置项 (在 config.py 或环境变量中设置):
| 配置项 | 默认值 | 说明 |
|---|---|---|
HOST |
0.0.0.0 | 服务器地址 |
PORT |
8000 | 服务器端口 |
UPLOAD_BASE_DIR |
/cpfs-nfs/sais/data-plaza-svc/datasets | 数据集基础路径 |
TEMP_DIR |
/data/uploads/temp | 临时文件目录 |
CHUNK_SIZE |
10MB | 分片大小 |
CHUNK_EXPIRE_HOURS |
24 | 分片过期时间(小时) |
ENABLE_MD5_CHECK |
true | 是否启用MD5校验 |
DATABASE_URL |
sqlite:///./tokens.db | 数据库连接URL(Token存储) |
环境配置
根据部署环境,只需要修改 UPLOAD_BASE_DIR 环境变量:
- Staging环境:
UPLOAD_BASE_DIR=/cpfs-nfs/sais/data-plaza-svc/datasets - Production环境:
UPLOAD_BASE_DIR=/normal-cpfs-datasets
文件最终会保存在: {UPLOAD_BASE_DIR}/{datasetName}/full/download/
Token认证配置
Token认证系统支持以下配置:
- 数据库存储: Token信息存储在MySQL/SQLite数据库中
- 永不过期: Token一旦生成,永久有效(除非手动撤销)
- 安全存储: Token使用SHA256哈希存储,不保存明文
- 权限控制: 支持用户角色、数据集访问权限和使用限制
Token格式
hf_<32位随机字符串>
用户角色
- admin: 管理员,可访问所有数据集和功能
- user: 普通用户,按配置的权限访问
- guest: 访客用户,受限的访问权限
项目结构
file-upload-server/
├── main.py # 主应用入口
├── config.py # 配置管理
├── models.py # 数据模型
├── services.py # 业务逻辑
├── routers.py # 路由定义
├── file_upload_sdk.py # Python SDK
├── sdk_usage_example.py # SDK使用示例
├── test_client.py # 测试客户端
├── setup.py # SDK打包配置
├── requirements.txt # 依赖包
├── Dockerfile # Docker镜像
├── .dockerignore # Docker忽略文件
├── env.example # 环境变量示例
└── README.md # 项目说明
开发指南
构建SDK包
# 构建wheel和tar.gz包
python setup.py sdist bdist_wheel
# 或者使用build工具
pip install build
python -m build
发布到PyPI(可选)
# 安装发布工具
pip install twine
# 上传到测试PyPI
twine upload --repository testpypi dist/*
# 上传到正式PyPI
twine upload dist/*
运行测试
pytest
代码检查
flake8 .
black .
部署建议
生产环境
- 使用反向代理: 建议使用 Nginx 作为反向代理
- 文件存储: 使用网络存储(如NFS)或对象存储
- 监控: 配置日志和监控系统
- 安全: 配置HTTPS和访问控制
性能优化
- 增加worker数量:
uvicorn main:app --workers 4 - 调整分片大小: 根据网络条件调整
CHUNK_SIZE - 使用SSD: 临时文件目录使用SSD存储
安全注意事项
Token安全
- 安全存储: 不要在代码中硬编码Token,使用环境变量或配置文件
- 定期轮换: 建议定期更新Token,虽然Token永不过期
- 最小权限: 只授予必要的权限,避免使用admin角色
- 及时撤销: 不再使用的Token应及时撤销
网络安全
- HTTPS: 生产环境必须使用HTTPS
- 防火墙: 配置适当的防火墙规则
- 访问控制: 限制允许访问的IP范围
许可证
此项目为内部使用项目
支持
如有问题请联系开发团队或提交 Issue
相关文档
- Token认证使用指南 - 详细的Token认证使用说明
- 上传记录功能指南 - 上传记录数据库存储和查询说明
- 上传记录API文档 - 上传记录查询接口使用文档(包含前端集成示例)
- API文档 - 在线交互式API文档
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file large_file_upload_sdk-3.1.0.tar.gz.
File metadata
- Download URL: large_file_upload_sdk-3.1.0.tar.gz
- Upload date:
- Size: 51.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.11.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
01cc9de7ecfd2a7f3b79eb2f1c7a4beddad1f673a44238927ed523e2246c2475
|
|
| MD5 |
f257d7631445dc43e8f56b1d8ef5c543
|
|
| BLAKE2b-256 |
489a04220f209b85d4dc6f5cb3b491a16c21d86af87f9414053d86c8971506a2
|
File details
Details for the file large_file_upload_sdk-3.1.0-py3-none-any.whl.
File metadata
- Download URL: large_file_upload_sdk-3.1.0-py3-none-any.whl
- Upload date:
- Size: 14.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.11.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6204d388beca06b53c6ccf72d908fff9a48d6fd31f9b0ed50baba8974219a434
|
|
| MD5 |
6157c4da20be000561756d69ab6dec1c
|
|
| BLAKE2b-256 |
380623fa2a7a524c24e5d1c0f8f0235d0e39d690d8711c343a2ff9c7e28add59
|