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 表记录
  • ✅ 删除关联表记录:MessageFile、MessageFeedback、MessageChain、MessageAgentThought 等
  • ❌ 不删除 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() 清理。

相关推荐
熊猫钓鱼>_>几秒前
越顺,越空:当 AI 把学习 “优化“ 到消失
人工智能·学习·ai·llm·agent·ai编程·metaai
2601_9567436816 分钟前
上海GEO优化公司名单(2026年10月更新):GEO是什么业务、上海主流服务商盘点与选型避坑指南
大数据·人工智能·技术分享·geo·上海
倔强的石头10618 分钟前
Qwen系列解析_阿里巴巴大模型技术路线
人工智能·大模型
liuchangng33 分钟前
类Jev项目Kev从入门到实战(6):Jev / Kev / Laya 对比
人工智能·jev·kev
Rocky Ding*35 分钟前
深入浅出完整解析FLUX.2、Seedream(即梦)、Z-image、Qwen-Image、GLM-Image核心基础知识
论文阅读·人工智能·深度学习·机器学习·aigc·扩散模型·ai-native
能源革命39 分钟前
AI 日报 · 2026-10-05
人工智能
Ivanqhz1 小时前
MLA、DSA、CSA、HCA
人工智能·算法·机器学习
网络毒刘1 小时前
GPT-6.1 Sol 定位速读:成本效率型编码模型与「何时该换本地 Agent」
人工智能·gpt·openai·agent·cursor
后端小肥肠1 小时前
Claude Opus 5.5 做视频:从口播稿到成片,全流程跑通
人工智能·aigc·agent
RockHopper20251 小时前
数字机制与未来企业运行模式(概要版)
人工智能·机器学习·智能体·agent 工程