news 2026/10/10 1:20:52

AIO Sandbox 浏览器下载完全指南:从 CDP 下载行为配置到文件落盘宿主机

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AIO Sandbox 浏览器下载完全指南:从 CDP 下载行为配置到文件落盘宿主机
  • AI Agent
  • 后端
  • MCP 服务
  • 浏览器控制
  • Agent 评测

【免费下载链接】sandbox

All-in-One Sandbox for AI Agents that combines Browser, Shell, File, MCP and VSCode Server in a single Docker container.

项目地址:https://gitcode.com/gh_mirrors/sandbox103/sandbox
点击查看免费下载

在 AIO Sandbox(All-in-One Sandbox for AI Agents)中,Chromium 浏览器下载的文件不会直接出现在宿主机上,而是先落入沙盒容器的文件系统中。本文以官方指南 browser-downloads.md 为核心,系统讲解浏览器下载的默认落盘位置、如何通过 CDP(Chrome DevTools Protocol)配置下载行为、如何用文件 API 查看与导出下载产物,以及下载链路的安全红线。读完本文,你将能够在自己搭建的 AI Agent 工作流中,完整打通"浏览器触发下载 → 沙盒内定位 → 文件 API 导出到宿主机"的闭环。

下载链路总览:为什么下载文件会"消失"在沙盒里

AIO Sandbox 把浏览器、Shell、文件系统、MCP 与 VSCode Server 整合进同一个 Docker 容器。因此 Chromium 进程写入的任何文件,都落在容器的隔离文件系统内,而不是宿主机磁盘上。这一点决定了浏览器下载处理的基本思路:

  • 下载产物由 Chromium 写入沙盒文件系统,路径固定、可控;
  • Shell 可以直接查看下载目录(因为 Shell 与浏览器共享同一套沙盒文件系统);
  • 文件 API 可以把产物拉回宿主机,实现跨容器传输。

换句话说,浏览器下载本质上被拆成了两步:第一步让 Chromium 把文件写进沙盒,第二步通过文件 API 把沙盒里的文件取出来。下面分别展开这两步的实操。

默认下载目录

Chromium 通常会遵循浏览器默认行为,把文件下载到当前运行用户的下载目录。AIO Sandbox 镜像内运行用户为gem,因此默认下载目录为:

/home/gem/Downloads

这是一个固定的已知路径,Agent 可以据此预测下载产物的落点,无需先探查用户目录结构。

用文件 API 列出下载目录

Sandbox 的 HTTP 服务默认监听8080端口(本地映射常为127.0.0.1:8080:8080),文件列表接口为POST /v1/file/list。列出下载目录:

curl -X POST "http://localhost:8080/v1/file/list" \ -H "Content-Type: application/json" \ -d '{"path": "/home/gem/Downloads"}'

从 SDK 源码看,这一接口在 Python 客户端中对应client.file.list_path(path=...)(见 sdk/python/agent_sandbox/file/client.py),底层请求路径即为v1/file/list。list_path还支持recursive(递归列出)、show_hidden(显示隐藏文件)、file_types(按扩展名过滤,如['.pdf', '.csv'])、include_size(附带文件大小)、sort_by(按 name/size/modified/type 排序)等可选参数,适合在下载目录文件较多时做精准检索。

通过 CDP 配置下载行为

在触发下载之前,先要通过 CDP 配置 Chromium 的下载行为。AIO Sandbox 的浏览器会话会暴露一个 CDP 地址,获取方式有两种:

  1. 通过 SDK:调用client.browser.get_info(),其返回结果中的cdp_url字段即为浏览器级 CDP 连接地址(接口定义见 sdk/python/agent_sandbox/browser/client.py);
  2. 直接请求:GET /v1/browser/info返回同样的信息。

方式一:通过 Playwright 连接 CDP

Playwright 等 CDP 客户端可以在触发下载前配置下载行为。示例(与官方指南一致):

from agent_sandbox import Sandbox from playwright.sync_api import sync_playwright client = Sandbox(base_url="http://localhost:8080") cdp_url = client.browser.get_info().cdp_url with sync_playwright() as p: browser = p.chromium.connect_over_cdp(cdp_url) page = browser.new_page() page.context.set_default_timeout(30_000)

这段代码里有两个关键点:

  • connect_over_cdp(cdp_url)是把 Playwright 附着到沙盒内已运行的 Chromium 实例上,而不是再启动一个新浏览器。仓库中的 examples/playwright-integration/main.py 使用异步写法playwright.chromium.connect_over_cdp(cdp_url)完成同样的连接,可以作为对照参考;
  • page.context.set_default_timeout(30_000)设置 30 秒默认超时,避免下载或页面加载期间操作挂起。

连接成功后,page上发生的页面交互(点击下载链接、触发window.print导出等)就会把文件写入沙盒下载目录。

方式二:直接在浏览器级 CDP 连接上调用Browser.setDownloadBehavior

如果你不依赖 Playwright,而是直接使用 Chrome DevTools Protocol,可以在浏览器级 CDP 连接上发送Browser.setDownloadBehavior命令:

{ "method": "Browser.setDownloadBehavior", "params": { "behavior": "allow", "downloadPath": "/home/gem/Downloads", "eventsEnabled": true } }

参数说明:

参数取值作用
behaviorallow/deny/defaultallow允许下载并写入downloadPath;deny阻止下载;default沿用浏览器默认行为
downloadPath沙盒内绝对路径下载文件的落盘目录,与默认下载目录保持一致即可(/home/gem/Downloads)
eventsEnabledtrue/false是否派发Browser.downloadWillBegin与Browser.downloadProgress事件,便于程序化跟踪下载进度

触发下载后如何确认完成

触发下载后,有两种方式确认下载结果:

  • 监听 CDP 事件:订阅Browser.downloadWillBegin(下载开始,包含下载项 GUID 与建议文件名)与Browser.downloadProgress(下载进度,携带state: completed/canceled等状态),据此判断下载何时结束;
  • 直接查询文件系统:通过文件 API 检查下载目录,POST /v1/file/list的返回中确认目标文件已出现。这种方式与事件监听互相独立,即使在 CDP 事件不可用或超时的情况下也能兜底。

下载文件到宿主机

确认下载产物已在沙盒内后,通过文件下载接口把文件拉回宿主机。文件下载接口为GET /v1/file/download,参数为沙盒内绝对路径:

curl -L \ "http://localhost:8080/v1/file/download?path=/home/gem/Downloads/report.pdf" \ --output report.pdf

这里的-L用于跟随可能的重定向;--output report.pdf把响应流写入宿主机本地文件。SDK 中对应方法为client.file.download_file(path=..., change_policy=...)(见 sdk/python/agent_sandbox/file/client.py),底层以流式方式消费响应字节,适合大文件下载。

用change_policy=abort防止读取到"写了一半"的文件

下载产物可能仍被后台进程(如正在落盘中的 Chromium)持续写入。若此时直接下载,可能拿到一个不完整或正在变化的文件。此时可以追加change_policy=abort:

curl -L \ "http://localhost:8080/v1/file/download?path=/home/gem/Downloads/report.pdf&change_policy=abort" \ --output report.pdf

change_policy的类型定义见 sdk/python/agent_sandbox/types/file_download_change_policy.py,可取两个值:

取值行为
ignore默认行为,不检测源文件变化,直接流式下发
abort服务端在开始传输前或传输过程中检测到源文件发生变化时,中断本次下载

从 SDK 底层实现(sdk/python/agent_sandbox/file/raw_client.py)可以看出:change_policy=abort时,若服务端检测到文件变化,接口会返回409 Conflict(SDK 中对应抛出ConflictError)。因此在使用该策略时,应把"收到 409"理解为"文件还在变化、需要稍后重试"的信号,而不是真正的失败。

用 SDK 下载的等价写法

不依赖 curl 时,也可以直接在 Python 里完成同样的下载:

from agent_sandbox import Sandbox client = Sandbox(base_url="http://localhost:8080") with open("report.pdf", "wb") as f: for chunk in client.file.download_file( path="/home/gem/Downloads/report.pdf", change_policy="abort", ): f.write(chunk)

这样可以把"触发下载 → 轮询目录 → 导出文件"全部收敛进一个 Python 脚本,便于在 Agent 循环里复用。

完整实战:一条龙脚本

把上面的要素组合起来,可以得到一个完整的下载闭环(触发下载 → 确认落盘 → 导出到宿主机):

import time from agent_sandbox import Sandbox from playwright.sync_api import sync_playwright client = Sandbox(base_url="http://localhost:8080") cdp_url = client.browser.get_info().cdp_url # 1. 触发下载 with sync_playwright() as p: browser = p.chromium.connect_over_cdp(cdp_url) page = browser.new_page() page.context.set_default_timeout(30_000) page.goto("https://example.com/report") page.click("a#download") # 2. 轮询等待下载完成 for _ in range(30): result = client.file.list_path(path="/home/gem/Downloads") if any(item.get("name") == "report.pdf" for item in result.items): break time.sleep(1) # 3. 导出到宿主机 with open("report.pdf", "wb") as f: for chunk in client.file.download_file( path="/home/gem/Downloads/report.pdf", change_policy="abort", ): f.write(chunk)

几点说明:

  • 步骤 2 的轮询用的是文件 API 而非 CDP 事件,即使 CDP 事件流断开也能完成确认;
  • 若下载本身耗时较长,可以把set_default_timeout(30_000)调大,或改用手动轮询;
  • change_policy="abort"保证导出的是一份"稳定"的文件,避免读到半成品。

与浏览器其他配置的衔接

下载行为与浏览器整体配置相互独立但常需协同。AIO Sandbox 支持通过环境变量在容器启动时配置浏览器(详见 browser-config.md),例如BROWSER_EXTRA_ARGS="--disable-dev-shm-usage"追加 Chromium 启动参数、BROWSER_USER_AGENT自定义 User-Agent、HOMEPAGE设置启动首页。这些配置影响页面如何渲染与请求行为,进而影响下载入口是否可用;而下载落盘路径则由 CDP 的downloadPath或浏览器默认行为决定,两者互不覆盖。

此外,运行时也可以通过以下 API 查看或更新浏览器状态:

  • GET /v1/browser/info:获取 CDP 地址、视口等信息(获取cdp_url的官方入口);
  • POST /v1/browser/config:调整分辨率等浏览器配置;
  • POST /v1/browser/restart:软重启(重连 Playwright 会话)或硬重启(经 supervisorctl 重启浏览器进程)。

安全建议

浏览器下载的文件本质上来自不可信的网页内容,处理时需遵循以下原则:

  • 将下载文件视为不可信输入。PDF、Office 文档、脚本等都可能携带恶意内容,Agent 解析或执行前应经过校验;
  • 除非用户明确需要,文件应保留在沙盒内处理。沙盒的隔离性是安全边界,把文件导出到宿主机前应确认其必要性;
  • 不要开启过宽的本地文件访问能力,除非任务确实需要。下载目录的读写、文件 API 的导出范围都应遵循最小权限原则,避免让 Agent 随意访问沙盒内外的大范围路径。

小结

本文围绕 browser-downloads.md 展开,完整覆盖了 AIO Sandbox 中浏览器下载的三个环节:

  1. 落盘:Chromium 把下载产物写入沙盒内的/home/gem/Downloads,可通过POST /v1/file/list查看;
  2. 配置:通过 Playwright 的connect_over_cdp或 CDP 的Browser.setDownloadBehavior设置下载行为,并用Browser.downloadWillBegin/Browser.downloadProgress事件或文件 API 确认下载完成;
  3. 导出:通过GET /v1/file/download?path=...&change_policy=abort把稳定版本的产物拉回宿主机。

配合 SDK 中的client.browser.get_info()、client.file.list_path()与client.file.download_file()(实现见 sdk/python/agent_sandbox/browser/client.py 与 sdk/python/agent_sandbox/file/client.py),这一链路可以完全编程化,直接嵌入到 AI Agent 的自动化循环中。

  • AI Agent
  • 后端
  • MCP 服务
  • 浏览器控制
  • Agent 评测

【免费下载链接】sandbox

All-in-One Sandbox for AI Agents that combines Browser, Shell, File, MCP and VSCode Server in a single Docker container.

项目地址:https://gitcode.com/gh_mirrors/sandbox103/sandbox
点击查看免费下载

相关推荐

上一篇:终极指南:3步定制Meilix Linux启动界面,打造专属系统门面
下一篇:终极解密:5步掌握Hunyuan3D-2高分辨率3D资产生成核心技术

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/10 1:20:12

8 步把文档变成知识库——一次企业知识库流程的工程化尝试

## 背景先说结论:企业文档散落各处、找人问半天这类重复劳动,值得用工具兜住。## 核心能力- 全程本地运行,原始文档与知识数据不出电脑- 8 步流水线自动化:解析→结构化→质检→复核→分片→向量库→验收- 内置本地大模型&#xf…

作者头像 李华
网站建设 2026/10/10 1:17:06

OPC UA Part 1 2025 RLV:从地址空间到工程避坑全解析

简介:包含IEC 62541-1:2025 RLV标准的完整英文电子原版,共94页,压缩包内为1个可搜索、可编辑、支持目录跳转与矢量放大的PDF文件,整体大小约1.54MB。该标准是OPC UA系列规范的第一部分,系统阐述设计目标、安全模型、地…

作者头像 李华
网站建设 2026/10/10 1:17:01

PMIC+MCU便携设备电源管理方案:从充电到低功耗实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华