# Handle files

> A step-by-step guide to registering an installed PWA as an OS-level file handler — declaring file_handlers in the manifest, wiring the launchQueue consumer, and falling back when the API is unavailable.

import CompatTable from '@components/CompatTable.astro';

**In one line:** declaring `file_handlers` in your Web App Manifest registers your
installed PWA with the OS as a handler for specific file types, so double-clicking or
"Open with"-ing a matching file launches your app with that file instead of you building
a separate import flow.

## 1. Declare file_handlers in the manifest

Per Chrome for Developers, each file handler needs an `action` URL within the app's
scope, an `accept` map of MIME types to file extensions, and an optional `icons` array
so the OS can show a file-type-specific icon instead of just the app icon:

```json
{
  "file_handlers": [
    {
      "action": "/open-csv",
      "accept": { "text/csv": [".csv"] },
      "icons": [
        { "src": "/icons/csv-icon.png", "sizes": "256x256", "type": "image/png" }
      ],
      "launch_type": "single-client"
    }
  ]
}
```

`launch_type` controls whether opening multiple matching files at once reuses a single app
window (`"single-client"`, the default) or, with `"multiple-clients"`, launches the app once
per file, each launch's `LaunchParams.files` array holding just that one file.

## 2. Consume the launched file with launchQueue

Per MDN, once the OS launches the app with a matching file, the app receives it through
`window.launchQueue.setConsumer()`:

```js
window.launchQueue.setConsumer(async (launchParams) => {
  if (!launchParams.files.length) {
    return;
  }
  const [fileHandle] = launchParams.files;
  const file = await fileHandle.getFile();
  const text = await file.text();
  renderCsv(text);
});
```

## Where it's supported

<CompatTable feature="manifest-file-handlers" />

Per Chrome for Developers, File Handling is "limited to desktop operating systems" in
Chromium's implementation — do not rely on it to associate files with the app on Android.

## 3. Detect support and fall back

Per Chrome for Developers, feature-detect with both `"launchQueue" in window` and
`"files" in LaunchParams.prototype`, since `launchQueue` alone does not confirm the
`files` parameter shape the consumer depends on. When either check fails, give users an
in-app way to open a file that doesn't depend on OS registration:

```js
function supportsFileHandling() {
  return 'launchQueue' in window && 'files' in LaunchParams.prototype;
}

if (supportsFileHandling()) {
  window.launchQueue.setConsumer(async (launchParams) => {
    if (!launchParams.files.length) return;
    const file = await launchParams.files[0].getFile();
    renderCsv(await file.text());
  });
} else {
  // No File Handling support here — fall back to a manual
  // <input type="file" accept=".csv"> picker in the UI.
  document.getElementById('open-file-input').hidden = false;
}
```

## What goes wrong

- [ ] `file_handlers` registration is desktop-only in Chromium, per Chrome for
      Developers — always ship an in-app file picker as the Android/fallback path.
- [ ] Feature-detect with both `"launchQueue" in window` and
      `"files" in LaunchParams.prototype`, per Chrome for Developers — checking
      `launchQueue` alone doesn't confirm the `files` parameter shape `setConsumer()`
      callbacks depend on.
- [ ] Per Chrome for Developers, `launchQueue` queues launches until a consumer is
      registered, and each launch is handled exactly once regardless of when the consumer
      is set — but the consumer function itself must still run before you can read the
      launched file, so don't gate its registration behind other async startup work.
- [ ] Firefox and Safari do not implement `file_handlers` — do not depend on OS-level file
      association as the only way into this feature.

## Where to go next

- [manifest: file_handlers support](/compatibility/manifest-file-handlers/) — the full
  compatibility data and `file_handlers` manifest reference.
- [Receive shared content (share target)](/guides/share-target/) — a related guide for
  receiving files and data shared from other apps via the OS share sheet.