Skip to content

文件上传与Artifact存储分享实现说明

DeerFlow提供了完整的文件上传和Artifact(Agent生成的文件、网页等)存储分享能力,采用线程隔离的存储架构,结合严格的安全机制,确保文件操作的安全性和可用性。


组件位置职责
上传APIapp/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定义虚拟路径到物理路径的映射规则
POST /api/threads/{thread_id}/uploads
Content-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文件(如果支持)
    }
    ]
    }
GET /api/threads/{thread_id}/uploads/list
DELETE /api/threads/{thread_id}/uploads/{filename}
  1. 请求校验:验证thread_id合法性,校验文件名是否包含路径遍历字符
  2. 目录创建:自动创建线程对应的上传目录(如果不存在)
  3. 文件存储:将文件写入物理存储路径
  4. 沙箱同步:非本地沙箱场景下,自动同步文件到沙箱环境
  5. 格式转换:检测文件类型,支持的文档格式自动转换为Markdown
  6. 结果返回:返回文件的物理路径、虚拟路径、访问URL等信息
  • PDF文档(.pdf
  • PowerPoint演示文稿(.ppt, .pptx
  • Excel表格(.xls, .xlsx
  • Word文档(.doc, .docx
{base_dir}/threads/{thread_id}/user-data/uploads/
  • base_dir优先级:
    1. 显式传入的路径参数
    2. DEER_FLOW_HOME环境变量
    3. 开发环境:backend/.deer-flow
    4. 默认:$HOME/.deer-flow
/mnt/user-data/uploads/{filename}

Agent可以直接通过read_file工具使用该路径读取文件内容。

/api/threads/{thread_id}/artifacts/mnt/user-data/uploads/{filename}

UploadsMiddleware中间件在每次Agent执行前自动处理上传文件:

  1. 从当前消息中提取新上传的文件信息
  2. 扫描线程上传目录获取所有历史上传文件
  3. 生成<uploaded_files>标签,包含所有文件的路径、大小等信息
  4. 将文件列表追加到用户消息中,让Agent感知到已上传的文件
  5. Agent可以直接通过虚拟路径读取文件内容

Agent生成的网页、文档、图片等产出物统称为Artifact,系统提供了完整的存储、预览、分享能力。

组件位置职责
Artifact服务APIapp/gateway/routers/artifacts.py提供Artifact访问、下载的HTTP接口
路径解析工具app/gateway/path_utils.py统一处理虚拟路径到物理路径的转换
展示工具packages/harness/deerflow/tools/builtins/present_file_tool.pyAgent调用present_files工具将生成的文件展示给用户
路径配置packages/harness/deerflow/config/paths.py统一的路径映射规则
{base_dir}/threads/{thread_id}/user-data/outputs/
/mnt/user-data/outputs/{filename}

Agent生成文件时需要保存到这个路径下才能被识别为Artifact。

/api/threads/{thread_id}/artifacts/mnt/user-data/outputs/{filename}
  1. 文件生成:Agent生成网页、报告等文件,必须保存到/mnt/user-data/outputs/路径下
  2. 展示调用:Agent调用present_files工具,传入需要展示的文件路径(工具会校验路径必须在/mnt/user-data/outputs/目录下,防止非法路径访问)
  3. 状态更新:工具将文件路径添加到线程状态的artifacts列表中
  4. 前端渲染:前端识别到artifacts列表中的文件,自动生成可访问的链接
  5. 用户访问:用户点击链接即可在线预览或下载文件
GET /api/threads/{thread_id}/artifacts/{virtual_path:path}
  • 支持?download=true参数强制下载文件
  • 自动识别MIME类型,根据文件类型返回对应响应:
    • 活跃内容类型(HTML/XHTML/SVG)强制下载,防止XSS攻击
    • 文本/图片等安全类型支持在线预览
    • 二进制文件默认提供下载
http://{your-deerflow-domain}/api/threads/{thread_id}/artifacts/{virtual_path}
  • URL包含thread_id和文件虚拟路径,可直接分享给其他用户访问
  • 所有访问都会经过权限校验,确保只有授权用户可以访问对应线程的文件

  • 所有路径解析都经过严格的边界检查,确保文件始终在对应线程的目录范围内
  • 自动过滤文件名中的路径遍历字符(..//等),防止目录穿越攻击
  • 每个线程的文件存储在独立的目录中,不同线程之间无法互相访问文件
  • 路径解析时严格校验thread_id与目录的对应关系
  • HTML、XHTML、SVG等包含可执行代码的内容类型强制作为附件下载,不会直接在浏览器中渲染
  • 所有文本内容返回时设置正确的Content-Type和安全Header
  • 上传文件名自动标准化处理,移除路径组件和特殊字符
  • 文件名冲突时自动重命名,避免覆盖现有文件
  • 所有文件访问都需要经过会话权限校验,确保只有线程参与者可以访问对应文件
  • 不允许访问线程目录之外的任何系统文件

  1. 文件大小限制:默认最大100MB,可通过Nginx配置的client_max_body_size调整
  2. 文件名长度:最大255字节
  3. 存储隔离:文件仅在当前线程内可见,无法跨线程访问
  4. 转换耗时:大文档转换为Markdown可能需要几秒到几十秒不等
  5. 存储清理:线程删除时会自动清理对应目录下的所有上传文件和生成的Artifact

前端提供了完整的上传和Artifact访问封装:

  • uploadFiles(threadId, files):上传多个文件到指定线程
  • listUploadedFiles(threadId):获取指定线程的所有上传文件
  • deleteUploadedFile(threadId, filename):删除指定上传文件
  • getArtifactUrl(threadId, virtualPath):生成Artifact访问URL
  • ArtifactLink组件:自动渲染Artifact链接,支持在线预览和下载