Skip to main content

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

本地开发

  1. 克隆项目
git clone <repository-url>
cd file-upload-server
  1. 安装依赖
pip install -r requirements.txt
  1. 配置环境变量
cp env.example .env
# 编辑 .env 文件,根据环境修改 UPLOAD_BASE_DIR
  1. 启动服务
python main.py

服务将在 http://localhost:8000 启动

Docker部署

  1. 构建镜像
docker build -t file-upload-server .
  1. 运行容器
# 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 .

部署建议

生产环境

  1. 使用反向代理: 建议使用 Nginx 作为反向代理
  2. 文件存储: 使用网络存储(如NFS)或对象存储
  3. 监控: 配置日志和监控系统
  4. 安全: 配置HTTPS和访问控制

性能优化

  1. 增加worker数量: uvicorn main:app --workers 4
  2. 调整分片大小: 根据网络条件调整 CHUNK_SIZE
  3. 使用SSD: 临时文件目录使用SSD存储

安全注意事项

Token安全

  1. 安全存储: 不要在代码中硬编码Token,使用环境变量或配置文件
  2. 定期轮换: 建议定期更新Token,虽然Token永不过期
  3. 最小权限: 只授予必要的权限,避免使用admin角色
  4. 及时撤销: 不再使用的Token应及时撤销

网络安全

  1. HTTPS: 生产环境必须使用HTTPS
  2. 防火墙: 配置适当的防火墙规则
  3. 访问控制: 限制允许访问的IP范围

许可证

此项目为内部使用项目

支持

如有问题请联系开发团队或提交 Issue

相关文档

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

large_file_upload_sdk-3.1.1.tar.gz (51.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

large_file_upload_sdk-3.1.1-py3-none-any.whl (13.9 kB view details)

Uploaded Python 3

File details

Details for the file large_file_upload_sdk-3.1.1.tar.gz.

File metadata

  • Download URL: large_file_upload_sdk-3.1.1.tar.gz
  • Upload date:
  • Size: 51.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.11.7

File hashes

Hashes for large_file_upload_sdk-3.1.1.tar.gz
Algorithm Hash digest
SHA256 e6ad47c1be172b5547b764d523b3526c4658a98d51e776cca08a5a4f3a2b63b7
MD5 426d220e49e91a9c4a0b9168553dcf32
BLAKE2b-256 adad3ea5da449c8873c2bda7df64d2f6a9bd19caec1caa393f2c01de8fe6ef80

See more details on using hashes here.

File details

Details for the file large_file_upload_sdk-3.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for large_file_upload_sdk-3.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ec8556bd49689b10c5349f457264ce9d3b6893f1fb32ba0ead88e6ffd6be7323
MD5 4ac223cbc245564635cf02925f674e70
BLAKE2b-256 71ac28c2ef3a2bb43b85caaad7f7745d66cea8f3a970b1242d4cf1529164bf21

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page