Skybridge 文件处理指南:useFiles 与 useDownload 实现文件上传、下载与打开的完整教程
【免费下载链接】skybridgeSkybridge is a full-stack TypeScript framework for MCP Apps and ChatGPT Apps. Type-safe. React-powered. Platform-agnostic.项目地址: https://gitcode.com/gh_mirrors/skybr/skybridge
本文带你快速上手Skybridge(一个面向 MCP Apps 与 ChatGPT Apps 的全栈 TypeScript 框架)中的两个文件处理 Hook:useFiles与useDownload。它们分别解决"文件如何进应用"(上传、选择文件)和"文件如何出应用"(保存到用户设备)两大核心问题,让你在对话式应用中轻松实现文件上传、下载与打开。
为什么 MCP Apps 需要专门的文件处理 Hook?
MCP Apps 的界面(View)运行在沙箱 iframe中,与普通网页不同:
- 🚫 无法直接访问用户磁盘
- 🚫 传统的
<a download>、URL.createObjectURL等下载方式被拦截 - 🚫 拿不到文件字节,只能拿到"文件引用"
Skybridge 通过宿主(ChatGPT、Claude 等)开放的桥接能力,把这套差异封装成两个简洁的 React Hook,你只需几行代码即可完成文件流转:
| Hook | 方向 | 支持宿主 | 核心能力 |
|---|---|---|---|
useFiles | 文件进应用 | ChatGPT | 上传本地文件、从 ChatGPT 文件库选文件、解析下载链接 |
useDownload | 文件出应用 | Claude | 把应用生成的内容保存到用户设备 |
useFiles:三步搞定文件上传与选择
useFiles返回三个函数(源码见 use-files.ts),分别对应"传文件进来"的三条路径:
1️⃣ upload:上传本地文件
把用户从设备选中的File交给宿主存储,返回文件元信息FileMetadata(含fileId、fileName、mimeType)。注意:宿主只给你引用,不给字节——这是安全设计,也简化了传输。
import { useFiles } from "skybridge/web"; const { upload } = useFiles(); const meta = await upload(file); // meta.fileId 即为持久句柄2️⃣ selectFiles:从 ChatGPT 文件库选文件
打开 ChatGPT 原生的文件库选择器,用户可挑选历史对话中已上传的文件授权给应用,返回一个FileMetadata数组(用户取消时为空数组)。
3️⃣ getDownloadUrl:把引用换成下载链接
fileId是持久的"钥匙",而download_url是临时缓存链接、会过期。因此最佳实践是:把fileId存进状态,需要时再用getDownloadUrl按需换取新链接:
const { downloadUrl } = await getDownloadUrl({ fileId: meta.fileId });💡 小提示:Hook 返回的是 camelCase 字段(
fileId),而传给工具的 FileRef 需要 snake_case 的file_id+ 必填的download_url,构建时要手动映射一下。
useDownload:一键把生成的文件保存到用户设备
Claude 端没有文件存储,唯一能做的"出向"操作就是让 View 把内容交还给宿主,由宿主确认后写入用户磁盘。useDownload直接返回一个download函数(源码见 use-download.ts)。
两种内容载体:
- 内联资源(
resource):文件内容直接随请求携带,文本用text字段,二进制用 base64 的blob字段 - 资源链接(
resource_link):只给一个 URL,由宿主自己去拉取(Claude 暂不支持此类型)
文件名由uri的最后一段决定,例如file:///receipt.csv会建议保存为receipt.csv。
import { useDownload } from "skybridge/web"; const download = useDownload(); const exportCsv = async () => { const csv = items.map((i) => `${i.label},${i.amount}`).join("\n"); const { isError } = await download({ contents: [{ type: "resource", resource: { uri: "file:///receipt.csv", mimeType: "text/csv", text: csv }, }], }); if (isError) console.warn("用户取消或宿主不支持下载"); };三个关键细节:
- ⏰ 返回值中的
isError为true表示用户取消或宿主拒绝;真正的失败(超时、断连)则会让 Promise 抛错 - 🖱️ 必须在用户点击等交互中触发,挂载时自动下载会被宿主拒绝
- 🔁 一次可传多个
contents,批量保存多个文件
实战案例:聊天里压缩文件并下载
官方示例 chatgpt-files 完整演示了useFiles的闭环:用户拖拽或从文件库选择一个文件 → 应用调用zip-file工具压缩 → 返回压缩包引用 → 用户点击下载。
核心流程只有四步(完整代码见 zip-file.tsx):
upload(picked)上传设备文件,拿到fileIdgetDownloadUrl({ fileId })换取临时下载链接- 组装成
FileRef(file_id+download_url)调用工具 - 工具返回新的
file_id,再次getDownloadUrl打开下载
服务端工具则用openai/fileParams声明文件入参,宿主会自动把用户附件路由进来(示例见 server.ts)。
开发过程中,还可以用 Skybridge 自带的 DevTools 面板在本地调试 View 与工具调用:
平台兼容性速查
| 能力 | ChatGPT | Claude |
|---|---|---|
useFiles(upload / selectFiles / getDownloadUrl) | ✅ | ❌ 抛出异常 |
FileRef文件参数(工具入参/出参) | ✅ | ❌ |
useDownload(保存文件到设备) | 视宿主能力 | ✅(仅内联资源) |
⚠️ 记住一句话:ChatGPT 有"文件仓库"可以双向搬运文件,Claude 只有"出口"。跨平台应用应做好能力检测与降级(比如文件库不可用时回退到本地上传)。
延伸阅读
- useFiles API 参考
- useDownload API 参考
- 文件处理指南(Handle Files)
- FileRef 文件引用类型
- useCallTool:把上传的文件转发给工具
- useOpenExternal:在应用外打开链接
掌握useFiles与useDownload之后,你的 MCP App 就具备了完整的文件处理能力——用户上传的票据能被工具解析,应用生成的报表也能一键落盘。结合 create-skybridge 模板 快速起步,几分钟就能搭出属于你的文件处理应用 🚀
【免费下载链接】skybridgeSkybridge is a full-stack TypeScript framework for MCP Apps and ChatGPT Apps. Type-safe. React-powered. Platform-agnostic.项目地址: https://gitcode.com/gh_mirrors/skybr/skybridge
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考