文件存储
概述
文件管理系统支持多存储后端、分块上传、MD5 秒传、临时令牌访问控制、AI OCR 识别等能力。
存储后端
通过 FILE_STORAGE_TYPE 配置切换存储后端:
| 类型 | 说明 | 配置项 |
|---|---|---|
local | 本地文件系统 | FILE_STORAGE_LOCAL_PATH |
oss | 阿里云 OSS | OSS_ENDPOINT, OSS_ACCESS_KEY_ID, OSS_ACCESS_KEY_SECRET, OSS_BUCKET_NAME |
minio | MinIO 对象存储 | MINIO_ENDPOINT, MINIO_ACCESS_KEY, MINIO_SECRET_KEY, MINIO_BUCKET_NAME |
azure | Azure Blob Storage | AZURE_ACCOUNT_NAME, AZURE_ACCOUNT_KEY, AZURE_CONTAINER_NAME |
存储后端抽象
所有存储后端实现统一的 StorageBackend 接口:
python
class StorageBackend:
def save(self, file_content, filename): ... # 保存文件
def delete(self, storage_path): ... # 删除文件
def exists(self, storage_path): ... # 检查是否存在
def get_url(self, storage_path): ... # 获取访问 URL
def get_size(self, storage_path): ... # 获取文件大小
def calculate_md5(self, file_content): ... # 计算 MD5
def generate_filename(self, original_name): ... # 生成唯一文件名通过工厂函数 get_storage_backend(config) 创建实例。
数据模型
FileManager
| 字段 | 类型 | 说明 |
|---|---|---|
name | String | 文件名 |
type | String | file / folder |
parent_id | String | 父文件夹 ID(逻辑外键) |
path | String | 完整路径 |
size | BigInteger | 文件大小(字节) |
file_ext | String | 文件扩展名 |
mime_type | String | MIME 类型 |
storage_type | String | 存储类型 |
storage_path | String | 存储路径 |
md5 | String | 文件 MD5 |
is_public | Boolean | 是否公开 |
is_system | Boolean | 是否系统文件夹 |
source | String | 来源模块(chat/form/avatar 等) |
FileAccessToken
| 字段 | 类型 | 说明 |
|---|---|---|
token | String | 访问令牌(唯一) |
file_id | String | 文件 ID |
expires_at | DateTime | 过期时间 |
user_id | String | 用户 ID |
核心功能
文件上传
POST /api/core/file_manager/upload
Content-Type: multipart/form-data
file: <binary>
parent_id: <optional>
is_public: false
source: form上传流程:
- 计算文件 MD5
- 检查是否存在相同 MD5(秒传)
- 存储到后端
- 创建数据库记录
文件自动归类
上传时传入 source 参数,系统自动创建 模块文件夹/年-月 两级系统文件夹:
| source | 文件夹名称 |
|---|---|
chat | 聊天文件 |
form | 表单附件 |
avatar | 头像 |
workflow | 工作流附件 |
announcement | 公告附件 |
ai_platform | AI平台文件 |
系统文件夹(is_system=true)受保护,不允许重命名和删除。
分块上传
适用于大文件,流程:
1. POST /chunk/init → 初始化(秒传检查)→ 返回 uploadId
2. POST /chunk/upload → 逐块上传到临时目录
3. GET /chunk/status → 查询上传进度
4. POST /chunk/merge → 合并分块 → 存储 → 数据库记录秒传:初始化时检查 fileHash(MD5),如已存在则直接返回 fileExists=true + fileId。
文件访问控制
| 访问方式 | 适用场景 | 安全性 |
|---|---|---|
公开访问 (is_public=true) | 头像、公告图片 | 无需认证 |
流式访问 (/stream/{id}) | 预览、下载 | 需要 JWT 或临时令牌 |
代理访问 (/proxy/{id}) | 内容分发 | 需要 JWT 或临时令牌 |
临时令牌 (FileAccessToken) | 限时分享 | 令牌 + 过期时间 |
临时令牌服务:
python
# 创建临时访问令牌(默认 1 小时)
token = await FileAccessTokenService.create_token(
db, file_id=file_id, expires_in=3600, user_id=user_id
)
# 验证令牌
file_token = await FileAccessTokenService.verify_token(db, token)
# 撤销令牌
await FileAccessTokenService.revoke_token(db, token)文本提取
从文件中提取文本内容,支持多种格式:
| 格式 | 说明 |
|---|---|
| txt/md/代码文件 | 直接读取 |
| csv | 读取文本 |
| PyPDF2 提取 | |
| docx | python-docx 提取 |
| xlsx | openpyxl 提取 |
| pptx | python-pptx 提取 |
AI OCR 识别
POST /api/core/file_manager/ocr/recognize
{
"fileId": "xxx",
"outputSchema": [...], // 结构化输出字段定义
"prompt": "提取发票信息" // 可选提示词
}处理流程:
- 图片文件:调用
qwen-vl-ocr模型进行 OCR 识别 - 文本文件:直接提取文本
- 结构化输出:使用 Function Calling 提取指定字段
API 列表
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /upload | 上传文件 |
| POST | /folder | 创建文件夹 |
| GET | / | 文件列表(分页) |
| GET | /tree | 文件夹树 |
| GET | /stream/{id} | 流式获取文件 |
| GET | /url/{id} | 获取文件 URL |
| PUT | /{id}/rename | 重命名 |
| PUT | /move | 移动文件 |
| DELETE | /{id} | 删除文件 |
| POST | /chunk/init | 初始化分块上传 |
| POST | /chunk/upload | 上传分块 |
| POST | /chunk/merge | 合并分块 |
| POST | /access-token | 创建临时令牌 |
| POST | /ocr/recognize | AI OCR 识别 |