Dify v1.15.0 Chatflow附件上传存储机制调研报告

Dify v1.15.0 Chatflow附件上传存储机制调研报告

一、文件上传完整流程

用户在 chatflow 中上传附件(图片、文档、视频、音频)时,流程如下:

bash 复制代码
用户上传文件 (multipart/form-data)
    │
    ▼
API Controller ── POST /files/upload
    ├── Web 应用:     api/controllers/web/files.py
    ├── Service API:  api/controllers/service_api/app/file.py
    └── Console:      api/controllers/console/files.py
    │
    ▼
FileService.upload_file()  ── api/services/file_service.py:43
    ├── 1. 校验扩展名黑名单 (UPLOAD_FILE_EXTENSION_BLACKLIST)
    ├── 2. 校验文件大小(按类型区分限制)
    ├── 3. 生成存储 key: upload_files/{tenant_id}/{uuid}.{ext}
    ├── 4. storage.save(key, content) → 写入存储后端
    ├── 5. 创建 UploadFile 数据库记录
    └── 6. 生成签名访问 URL (source_url)

二、文件存储在哪里?

存储后端类型

由环境变量 STORAGE_TYPE 控制,支持 13 种存储后端(storage_type.py):

类型 说明
opendal (默认) OpenDAL 统一存储,支持 fs/s3/azblob/gcs 等多种 scheme
s3 AWS S3
azure-blob Azure Blob Storage
aliyun-oss 阿里云 OSS
tencent-cos 腾讯云 COS
huawei-obs 华为云 OBS
google-storage Google Cloud Storage
volcengine-tos 火山引擎 TOS
oci-storage Oracle Cloud
supabase Supabase Storage
local (已废弃) 底层仍使用 OpenDAL fs scheme

存储路径

  • 逻辑路径upload_files/{tenant_id}/{uuid}.{extension}
  • Docker 本地存储物理路径./volumes/app/storage → 映射到容器内 /app/api/storage/
    • 完整路径示例:/app/api/storage/upload_files/{tenant_id}/{uuid}.jpg

数据库记录

文件信息记录在 upload_files 表中(api/models/model.py:2255),关键字段:

字段 说明
id UUID
tenant_id 租户 ID
storage_type 存储类型
key 存储路径
name 原始文件名
size 文件大小(字节)
extension / mime_type 文件类型
hash SHA3-256 哈希
source_url 签名访问 URL
created_at 创建时间

文件与消息的关联通过 message_files 表(api/models/model.py:1876)中的 upload_file_id 字段关联。

三、文件存储多久?是否会自动删除?

⚠️ 核心结论:上传的附件文件不会自动删除,会永久保留

Dify 没有 针对 upload_files 的 TTL/过期自动清理机制。具体分析:

1. clean_messages 定时任务 --- 只删数据库记录,不删文件

clean_messages.py 中的 clean_messages 任务(默认关闭 ,需 ENABLE_CLEAN_MESSAGES=true):

  • ✅ 删除 messages 表记录
  • ✅ 删除关联表记录:MessageFileMessageFeedbackMessageChainMessageAgentThought
  • 不删除 upload_files 表记录
  • 不删除 存储后端中的实际文件

关键代码(messages_clean_service.py:570-580):

python 复制代码
# _batch_delete_message_relations 方法中:
session.execute(delete(MessageFile).where(MessageFile.message_id.in_(message_ids)))
# ↑ 只删除 message_files 关联记录,不触碰 upload_files 表和存储
2. 其他定时任务也不涉及上传文件清理
任务 说明 删除存储文件?
clean_embedding_cache_task 清理 embedding 缓存
clean_unused_datasets_task 清理未使用的数据集
clean_workflow_runlogs_precise 清理 workflow 日志记录
mail_clean_document_notify_task 发送邮件通知
3. 唯一会自动删除文件的场景:删除 App

当删除整个 App 时,remove_app_and_related_data_task(remove_app_and_related_data_task.py)会级联删除关联的存储文件。

四、如何手动删除?

方法 1:通过 API 删除单个文件

FileService.delete_file()api/services/file_service.py:260):

python 复制代码
def delete_file(self, file_id: str):
    with self._session_maker() as session, session.begin():
        upload_file = session.scalar(select(UploadFile).where(UploadFile.id == file_id))
        if not upload_file:
            return
        storage.delete(upload_file.key)    # 删除存储中的实际文件
        session.delete(upload_file)         # 删除数据库记录

方法 2:删除整个 App(级联删除)

删除 App 时会自动清理该 App 关联的所有上传文件。

方法 3:直接操作存储和数据库

对于本地存储,可直接删除文件系统中的文件:

bash 复制代码
# Docker 环境
rm /app/api/storage/upload_files/{tenant_id}/{file_uuid}.{ext}

同时清理数据库记录:

sql 复制代码
DELETE FROM upload_files WHERE key = 'upload_files/{tenant_id}/{file_uuid}.{ext}';

五、相关环境变量/全局配置

存储配置

环境变量 默认值 说明
STORAGE_TYPE opendal 存储后端类型
OPENDAL_SCHEME fs OpenDAL scheme
OPENDAL_FS_ROOT storage 本地存储根目录
S3_ENDPOINT / S3_BUCKET_NAME / ... - S3 配置

文件上传限制

环境变量 默认值 说明
UPLOAD_FILE_SIZE_LIMIT 15 通用文件大小上限 (MB)
UPLOAD_IMAGE_FILE_SIZE_LIMIT 10 图片上限 (MB)
UPLOAD_VIDEO_FILE_SIZE_LIMIT 100 视频上限 (MB)
UPLOAD_AUDIO_FILE_SIZE_LIMIT 50 音频上限 (MB)
UPLOAD_FILE_BATCH_LIMIT 5 单次上传批量上限
WORKFLOW_FILE_UPLOAD_LIMIT 10 Workflow 上传文件数上限
UPLOAD_FILE_EXTENSION_BLACKLIST (空) 禁止上传的扩展名
FILES_ACCESS_TIMEOUT 300 签名 URL 过期时间(秒)

清理任务配置

环境变量 默认值 说明
ENABLE_CLEAN_MESSAGES false 启用消息清理任务(不删文件
SANDBOX_EXPIRED_RECORDS_RETENTION_DAYS - 消息保留天数
ENABLE_WORKFLOW_RUN_CLEANUP_TASK false 启用 workflow run 清理

六、总结

flowchart TD A[用户上传附件] --> B[FileService.upload_file] B --> C[存储到 STORAGE_TYPE 指定的后端] B --> D[记录到 upload_files 表] D --> E[关联到 message_files 表] C --> F["⚠️ 永久保留\n无自动清理"] D --> F G[clean_messages 定时任务] -->|仅删除| H[message_files 关联记录] G -.->|❌ 不删除| D G -.->|❌ 不删除| C I[手动删除方式] --> J[FileService.delete_file] I --> K[删除 App 级联删除] I --> L[直接操作存储+DB]
问题 答案
文件存储在哪里? STORAGE_TYPE 决定,默认 OpenDAL 本地文件系统 (/app/api/storage/upload_files/{tenant_id}/)
存储多久? 永久,没有 TTL 或过期机制
是否自动删除? clean_messages 任务只删消息数据库记录,不删上传文件
如何手动删除? FileService.delete_file(file_id) / 删除 App 级联删除 / 直接操作存储
全局变量控制? STORAGE_TYPE 控制存储位置;ENABLE_CLEAN_MESSAGES 控制消息清理(但不清理文件);各类 UPLOAD_* 控制上传限制

⚠️ 重要提示 :如果你需要自动清理上传的附件文件,目前 Dify 没有内置此功能 ,需要自行实现定时任务,扫描 upload_files 表中未被引用的记录并调用 storage.delete() 清理。

相关推荐
zhiSiBuYu05171 小时前
RAG 性能优化与缓存策略实战指南
人工智能·python·机器学习
大鱼>1 小时前
智能喂食器远程控制系统:硬件设计与软件实现
人工智能·iot·宠物
苏州邦恩精密1 小时前
浙江蔡司3D扫描仪应用领域及厂家选择分析
人工智能·科技·3d·自动化·制造
想会飞的蒲公英1 小时前
集成学习入门:Bagging、Boosting 到底在组合什么
人工智能·python·机器学习·集成学习·boosting
海外数字观察家1 小时前
品未云:博兹瓦纳华商批发零售一体化 ERP,破解本土软件适配难题|CSDN 技术分享
大数据·网络·人工智能·博兹瓦纳进销存系统·博兹瓦纳收银系统·博兹瓦纳erp系统·博兹瓦纳仓库管理系统
_老码1 小时前
AI-reader阅读助手开发过程
人工智能·python·ai
weixin_422329311 小时前
AgentScope Java ReActAgent 核心循环深度解析
java·开发语言·人工智能
SNKXD_11 小时前
2026年五款AI数字人系统效果差异:基于多维度横评的实证比较
大数据·人工智能
Lucky_5566881 小时前
山东捷瑞检测科技有限公司:政务信息化项目监理要点与收费标准解析
大数据·人工智能