# 文件

应用运行在隔离环境里，没有登录态，也不能访问网络，所以不能使用 `/api/files/...` 这类站内地址，也不能使用站外链接。要显示用户文件空间里的图片，请通过宿主读取。

需要先在 `app.json` 里声明 `files.read`。用户第一次打开应用时会看到「可以读取你文件里的图片等内容」并确认。

```json
{
  "formatVersion": 1,
  "sdk": { "major": 1, "minMinor": 0 },
  "entry": "index.js",
  "capabilities": {
    "required": ["data.read"],
    "optional": ["files.read"]
  }
}
```

## platform.files.url(fileId)

返回一个 `blob:` 地址，可以直接给 `<img src>` 或 `<a href>` 使用。同一个文件在应用运行期间只读取一次，之后复用同一个地址。文件不存在、已被删除或超过 8MB 时拒绝 Promise，失败不会被缓存，之后可以重试。

`fileId` 是文件的 ID。让茄总在对话里把文件放进应用时，它会用 `get_file_link` 取得这个 ID 并写进应用源码；你自己写应用时，把 ID 保存在数据记录里即可，不要写死在源码里，这样换一张图不需要改应用。

```js
export default async function render(root, platform) {
  const ui = platform.ui;
  const image = document.createElement("img");
  image.alt = "封面";
  image.style.maxWidth = "100%";
  try {
    image.src = await platform.files.url("文件 ID");
  } catch {
    root.replaceChildren(ui.page([ui.card([ui.hint("图片暂时无法显示")])]));
    return;
  }
  root.replaceChildren(ui.page([ui.card([image])]));
}
```

## platform.files.read(fileId)

返回 `{ name, mimeType, size, data }`，其中 `data` 是 base64 文本。只在需要自己处理字节时使用，显示图片优先用 `url`。

## 限制

- 只能读取当前登录用户自己的文件，单个文件最大 8MB。
- 只能读取，不能上传、改名或删除。
- 沙盒不放行音频和视频的内联播放，可以先用 `url` 提供下载链接。
- 没有声明 `files.read`，或用户没有授权时，调用会被拒绝，`platform.can("files.read")` 返回 `false`。
