文件上传与Artifact存储分享实现说明
DeerFlow提供了完整的文件上传和Artifact(Agent生成的文件、网页等)存储分享能力,采用线程隔离的存储架构,结合严格的安全机制,确保文件操作的安全性和可用性。
一、文件上传实现
Section titled “一、文件上传实现”1. 核心组件
Section titled “1. 核心组件”| 组件 | 位置 | 职责 |
|---|---|---|
| 上传API | app/gateway/routers/uploads.py | 提供文件上传、列表、删除的HTTP接口 |
| 上传管理器 | packages/harness/deerflow/uploads/manager.py | 上传核心逻辑,包括路径校验、文件存储、格式转换、URL生成 |
| 上传中间件 | packages/harness/deerflow/agents/middlewares/uploads_middleware.py | 自动将上传文件列表注入到Agent上下文 |
| 文件转换工具 | packages/harness/deerflow/utils/file_conversion.py | 支持Office文档、PDF等格式自动转换为Markdown |
| 路径配置 | packages/harness/deerflow/config/paths.py | 定义虚拟路径到物理路径的映射规则 |
2. 上传接口定义
Section titled “2. 上传接口定义”POST /api/threads/{thread_id}/uploadsContent-Type: multipart/form-data- 参数:
files多文件列表 - 返回:
{"success": true,"files": [{"filename": "document.pdf","physical_path": "/path/to/threads/123/user-data/uploads/document.pdf","virtual_path": "/mnt/user-data/uploads/document.pdf","url": "/api/threads/123/artifacts/mnt/user-data/uploads/document.pdf","size": 102400,"converted_md": "/mnt/user-data/uploads/document.pdf.md" // 转换后的Markdown文件(如果支持)}]}
列出已上传文件
Section titled “列出已上传文件”GET /api/threads/{thread_id}/uploads/listDELETE /api/threads/{thread_id}/uploads/{filename}3. 完整上传流程
Section titled “3. 完整上传流程”- 请求校验:验证
thread_id合法性,校验文件名是否包含路径遍历字符 - 目录创建:自动创建线程对应的上传目录(如果不存在)
- 文件存储:将文件写入物理存储路径
- 沙箱同步:非本地沙箱场景下,自动同步文件到沙箱环境
- 格式转换:检测文件类型,支持的文档格式自动转换为Markdown
- 结果返回:返回文件的物理路径、虚拟路径、访问URL等信息
4. 支持自动转换的格式
Section titled “4. 支持自动转换的格式”- PDF文档(
.pdf) - PowerPoint演示文稿(
.ppt,.pptx) - Excel表格(
.xls,.xlsx) - Word文档(
.doc,.docx)
5. 存储路径规则
Section titled “5. 存储路径规则”物理存储路径(主机侧)
Section titled “物理存储路径(主机侧)”{base_dir}/threads/{thread_id}/user-data/uploads/base_dir优先级:- 显式传入的路径参数
DEER_FLOW_HOME环境变量- 开发环境:
backend/.deer-flow - 默认:
$HOME/.deer-flow
虚拟路径(Agent沙箱内可见)
Section titled “虚拟路径(Agent沙箱内可见)”/mnt/user-data/uploads/{filename}Agent可以直接通过read_file工具使用该路径读取文件内容。
/api/threads/{thread_id}/artifacts/mnt/user-data/uploads/{filename}6. Agent集成
Section titled “6. Agent集成”UploadsMiddleware中间件在每次Agent执行前自动处理上传文件:
- 从当前消息中提取新上传的文件信息
- 扫描线程上传目录获取所有历史上传文件
- 生成
<uploaded_files>标签,包含所有文件的路径、大小等信息 - 将文件列表追加到用户消息中,让Agent感知到已上传的文件
- Agent可以直接通过虚拟路径读取文件内容
二、Artifact存储与分享实现
Section titled “二、Artifact存储与分享实现”Agent生成的网页、文档、图片等产出物统称为Artifact,系统提供了完整的存储、预览、分享能力。
1. 核心组件
Section titled “1. 核心组件”| 组件 | 位置 | 职责 |
|---|---|---|
| Artifact服务API | app/gateway/routers/artifacts.py | 提供Artifact访问、下载的HTTP接口 |
| 路径解析工具 | app/gateway/path_utils.py | 统一处理虚拟路径到物理路径的转换 |
| 展示工具 | packages/harness/deerflow/tools/builtins/present_file_tool.py | Agent调用present_files工具将生成的文件展示给用户 |
| 路径配置 | packages/harness/deerflow/config/paths.py | 统一的路径映射规则 |
2. 存储路径规则
Section titled “2. 存储路径规则”物理存储路径(主机侧)
Section titled “物理存储路径(主机侧)”{base_dir}/threads/{thread_id}/user-data/outputs/虚拟路径(Agent沙箱内路径)
Section titled “虚拟路径(Agent沙箱内路径)”/mnt/user-data/outputs/{filename}Agent生成文件时需要保存到这个路径下才能被识别为Artifact。
/api/threads/{thread_id}/artifacts/mnt/user-data/outputs/{filename}3. 生成与展示流程
Section titled “3. 生成与展示流程”- 文件生成:Agent生成网页、报告等文件,必须保存到
/mnt/user-data/outputs/路径下 - 展示调用:Agent调用
present_files工具,传入需要展示的文件路径(工具会校验路径必须在/mnt/user-data/outputs/目录下,防止非法路径访问) - 状态更新:工具将文件路径添加到线程状态的
artifacts列表中 - 前端渲染:前端识别到
artifacts列表中的文件,自动生成可访问的链接 - 用户访问:用户点击链接即可在线预览或下载文件
4. 访问与分享
Section titled “4. 访问与分享”GET /api/threads/{thread_id}/artifacts/{virtual_path:path}- 支持
?download=true参数强制下载文件 - 自动识别MIME类型,根据文件类型返回对应响应:
- 活跃内容类型(HTML/XHTML/SVG)强制下载,防止XSS攻击
- 文本/图片等安全类型支持在线预览
- 二进制文件默认提供下载
分享URL格式
Section titled “分享URL格式”http://{your-deerflow-domain}/api/threads/{thread_id}/artifacts/{virtual_path}- URL包含
thread_id和文件虚拟路径,可直接分享给其他用户访问 - 所有访问都会经过权限校验,确保只有授权用户可以访问对应线程的文件
三、安全机制
Section titled “三、安全机制”1. 路径遍历防护
Section titled “1. 路径遍历防护”- 所有路径解析都经过严格的边界检查,确保文件始终在对应线程的目录范围内
- 自动过滤文件名中的路径遍历字符(
../、/等),防止目录穿越攻击
2. 线程隔离
Section titled “2. 线程隔离”- 每个线程的文件存储在独立的目录中,不同线程之间无法互相访问文件
- 路径解析时严格校验
thread_id与目录的对应关系
3. XSS防护
Section titled “3. XSS防护”- HTML、XHTML、SVG等包含可执行代码的内容类型强制作为附件下载,不会直接在浏览器中渲染
- 所有文本内容返回时设置正确的Content-Type和安全Header
4. 文件名安全校验
Section titled “4. 文件名安全校验”- 上传文件名自动标准化处理,移除路径组件和特殊字符
- 文件名冲突时自动重命名,避免覆盖现有文件
5. 权限控制
Section titled “5. 权限控制”- 所有文件访问都需要经过会话权限校验,确保只有线程参与者可以访问对应文件
- 不允许访问线程目录之外的任何系统文件
四、限制说明
Section titled “四、限制说明”- 文件大小限制:默认最大100MB,可通过Nginx配置的
client_max_body_size调整 - 文件名长度:最大255字节
- 存储隔离:文件仅在当前线程内可见,无法跨线程访问
- 转换耗时:大文档转换为Markdown可能需要几秒到几十秒不等
- 存储清理:线程删除时会自动清理对应目录下的所有上传文件和生成的Artifact
五、前端集成
Section titled “五、前端集成”前端提供了完整的上传和Artifact访问封装:
uploadFiles(threadId, files):上传多个文件到指定线程listUploadedFiles(threadId):获取指定线程的所有上传文件deleteUploadedFile(threadId, filename):删除指定上传文件getArtifactUrl(threadId, virtualPath):生成Artifact访问URLArtifactLink组件:自动渲染Artifact链接,支持在线预览和下载