文件读写与上传下载
文件系统操作通过沙箱运行时 API 执行。SDK 会隐藏运行时鉴权、Connect RPC Header 以及上传/下载路由差异。
写入和读取文件
Section titled “写入和读取文件”await sandbox.files.write("/root/workspace/hello.txt", "hello\n");const text = await sandbox.files.read("/root/workspace/hello.txt");console.log(text);sandbox.files.write("/root/workspace/hello.txt", "hello\n")text = sandbox.files.read("/root/workspace/hello.txt")print(text)files, _ := sbx.Files()_, _ = files.Write(ctx, "/root/workspace/hello.txt", []byte("hello\n"))body, _ := files.Read(ctx, "/root/workspace/hello.txt", nil)await sandbox.files.makeDir("/root/workspace/app");await sandbox.files.write("/root/workspace/app/index.html", "<h1>Hello</h1>");const entries = await sandbox.files.list("/root/workspace/app");console.log(entries);上传本地文件
Section titled “上传本地文件”快速迭代时,可由应用读取本地文件,再写入沙箱:
const html = await fs.promises.readFile("./index.html", "utf8");await sandbox.files.write("/root/workspace/frontend/index.html", html);如果源码和依赖准备需要复用,应在模板构建阶段使用 Template.copy(...) 上传,而不是每次新建沙箱都上传。
运行时上传与下载路由
Section titled “运行时上传与下载路由”优先使用 SDK helper。调试原始运行时流量时,常见路由如下:
| 路由 | 用途 |
|---|---|
GET {envdUrl}/file?path=<path> | 读取原始文件字节。 |
POST {envdUrl}/file?path=<path> | 写入原始文件字节。 |
GET {envdUrl}/files/content?path=<path> | 以结构化响应读取文件内容。 |
POST {envdUrl}/files | 上传 multipart 内容。 |
POST {envdUrl}/files/batch | 批量写入文件。 |
POST {envdUrl}/files/compose | 从多个源文件组合输出。 |
所有路由都需要 X-Access-Token: <envdAccessToken>。
目标 SDK/运行时开启后,可通过运行时文件系统能力监听目录。当 Agent 写入输出文件时,编排方可以据此响应。
const watcher = await sandbox.files.watchDir("/root/workspace/output", { recursive: true,});
for await (const event of watcher) { console.log(event.type, event.path);}路径与持久化规则
Section titled “路径与持久化规则”| 规则 | 原因 |
|---|---|
| 优先使用绝对路径 | 避免模板 workdir 带来的歧义。 |
| 持久文件写入挂载路径 | 持久化由 volumeMounts[].path 控制,不由 workdir 控制。 |
将 ephemeral 视为沙箱生命周期存储 | 删除沙箱后文件消失。 |
| 不把产物写入日志 | 生成文件可能包含密钥或用户数据。 |
| 存储类型 | 持久化行为 |
|---|---|
ephemeral | 仅在沙箱生命周期内存在。 |
nfs | 共享 NFS 路径。 |
block | PVC 后端卷。 |
object | 同步到对象存储,取决于运行时同步策略。 |
对于 object-backed 存储,删除沙箱前需要等待模板文档中约定的 runtime sync/flush 行为完成。