# Manifest 文件处理程序（file_handlers）

> file_handlers 清单字段如何将已安装的 PWA 注册为特定文件类型的系统级处理程序，以及 window.launchQueue 如何把打开的文件传递给应用代码。

**一句话：** `file_handlers` 是一个对象数组，将已安装的 PWA 注册为操作系统层面某一组文件类型的处理程序，因此打开匹配的文件会启动该应用——应用随后需要通过自身 JavaScript 中的 `window.launchQueue` 读取该文件。

## 语法

```json
{
  "file_handlers": [
    {
      "action": "/handle-audio-file",
      "accept": {
        "audio/wav": [".wav"],
        "audio/x-wav": [".wav"],
        "audio/mpeg": [".mp3"],
        "audio/mp4": [".mp4"],
        "audio/aac": [".adts"],
        "audio/ogg": [".ogg"],
        "application/ogg": [".ogg"],
        "audio/webm": [".webm"],
        "audio/flac": [".flac"],
        "audio/mid": [".rmi", ".mid"]
      }
    }
  ]
}
```

`file_handlers` 数组中的每个对象都需要：

| 属性 | 是否必填 | 说明 |
|---|---|---|
| `action` | 是 | 文件被处理时导航到的 URL。必须位于 PWA 的导航域内——默认使用 `start_url`，也可通过 `scope` 设置。 |
| `accept` | 是 | 一个对象，键为 MIME 类型，值为与该 MIME 类型关联的文件扩展名字符串数组。 |

## 注册只负责启动应用——处理文件仍需自己实现

`file_handlers` 将 PWA 注册到操作系统，使打开匹配文件时启动该应用，但 PWA 本身仍需在 JavaScript 中实际处理该文件："this only results in the operating system launching the PWA when a matching file is opened. The PWA then needs to actually handle the file using JavaScript code."（这只会使操作系统在打开匹配文件时启动该 PWA，PWA 随后需要用 JavaScript 代码真正处理该文件。）其他应用也可能注册为同一文件类型的处理程序，操作系统如何让用户在多个处理程序间选择因设备而异。

## 用 window.launchQueue 读取文件

文件处理在应用运行于主线程的代码中完成，而不是在 service worker 中。使用 `window.launchQueue.setConsumer()` 读取传递给启动的文件：

```js
async function playSong(handledFile) {
  const blob = await handledFile.getFile();
  const url = window.URL.createObjectURL(blob);
  const audio = new Audio(url);
  audio.play();
}

if ("launchQueue" in window) {
  window.launchQueue.setConsumer((launchParams) => {
    if (launchParams.files && launchParams.files.length) {
      playSong(launchParams.files[0]);
    }
  });
}
```

## 单一启动与多次启动

`launch_type` 属性控制一次打开多个文件时是在单个客户端中打开，还是在多个客户端中分别打开；默认值为 `"single-client"`。设置为在多个客户端中打开时，每次启动是独立的，且每次启动的 `LaunchParams.files` 数组只有一个元素。该字段受平台限制：Windows 从不会以多个文件启动应用，而是以单个文件多次启动应用，因此 `launch_type` 在 Windows 上没有效果，所有启动实际上都等同于 `"multiple-clients"`。

## 权限提示会拦截访问

当 File Handling API 打开文件时，会在 PWA 查看文件之前显示权限提示，该提示会在用户选择用此 PWA 打开文件后立即出现。此权限提示会每次都显示，直到用户点击允许或阻止，或忽略提示达三次为止。当清单更新且检测到 `file_handlers` 部分发生变化时，权限会被重置。用户也可以在操作系统层面更改文件类型关联，这不受浏览器控制。

## 平台支持

File Handling 目前仅限桌面操作系统，且仅限 Chromium 内核：Chrome 102+ 与 Edge 102+ 支持；Firefox 与 Safari 不支持。

## 实践清单

- [ ] 每个 `action` URL 都位于 PWA 的导航域内。
- [ ] `accept` 列出了处理程序支持的所有 MIME 类型与扩展名。
- [ ] 使用前用 `"launchQueue" in window` 守卫 `window.launchQueue.setConsumer()`。
- [ ] 文件读取发生在页面/应用代码中，而非 service worker 中。
- [ ] 如需多个文件在不同客户端中分别打开，已明确设置 `launch_type`。
- [ ] 已在支持的桌面浏览器上安装 PWA 后，测试从操作系统文件管理器打开匹配文件。

## 在线试用

配套演示 [/demo/#file-handling](/demo/#file-handling) 在 manifest 中为 `.txt` 与 `.md` 声明了 `file_handlers`，页面加载时消费 `window.launchQueue`，并通过按钮用 `showOpenFilePicker()` 打开同类文件。它只读取文件名和大小。

## 相关链接

- [Manifest 快捷方式（shortcuts）](/zh/reference/manifest/shortcuts/) —— 另一个为已安装 PWA 添加系统级入口的清单字段