拡張子に Web アプリを関連付ける File Handling API の使い方
はじめに
File Handling API がデフォルトで有効化された Chrome 102 と Edge 102 がリリースされました。この機能により、 MIME タイプや拡張子に Web アプリを関連付けて開けるようになります。派手な機能のわりには全然話題になっていないように感じるのですが、気のせいでしょうか?
私は DXF(CAD 用のファイル形式の 1 つ)の中身を覗くツールを Web アプリとして作っています。試しに拡張子 .dxf
を当該アプリに関連付けられるようにしてみました。
実装
ざっくり言うとこれだけです。
- マニフェストに
file_handlers
フィールドを持たせる - スクリプトから
window.launchQueue.setConsumer()
を呼び出して、関連付けて開かれたファイルを取得する
ファイルを取得しさえすれば、あとは <input type="file">
などと同様 File インターフェイスに基づいてファイルを処理できます。
manifest.webmanifest
{
"name": "DXF Explorer",
"theme_color": "#3ab",
"icons": [
{
"src": "favicon.png",
"sizes": "192x192",
"type": "image/png"
}
],
"file_handlers": [
{
"action": ".",
"accept": {
"application/dxf": [".dxf"]
},
"icons": [
{
"src": "favicon.png",
"sizes": "192x192",
"type": "image/png"
}
],
"launch_type": "multiple-clients"
}
]
}
マニフェストファイル(Web Application Manifest)です。今回の主役は file_handlers
で、 action
には関連付けて開く URL を、 accept
には関連付ける MIME タイプ/拡張子を指定します。 launch_type
には複数ファイルを一度に開くときの挙動を指定します: "multiple-clients"
を指定するとファイルごとにアプリが立ち上がりますが、デフォルト("single-client"
)ではアプリが 1 つだけ立ち上がって複数ファイルをまとめて受け取ります。
このマニフェストファイルを HTML ファイルから参照します。
<head>
...
<link rel="manifest" href="manifest.webmanifest">
...
</head>
index.ts
// https://wicg.github.io/manifest-incubations/index.html#launch-queue-and-launch-params
// https://chromium.googlesource.com/chromium/src/+/refs/heads/main/third_party/blink/renderer/modules/launch/
interface LaunchQueue {
setConsumer(consumer: (params: LaunchParams) => unknown): void
}
interface LaunchParams {
readonly targetURL: string
readonly files: readonly (FileSystemFileHandle | FileSystemDirectoryHandle)[]
}
declare global {
interface Window {
readonly launchQueue?: LaunchQueue | undefined
}
}
const handleFile = (file: File) => {
// handle file
}
window.launchQueue?.setConsumer(async ({ files }) => {
if (files.length === 1 && files[0].kind === 'file') {
handleFile(await files[0].getFile())
}
})
TypeScript のソースコードです。前半は型定義です。いつか lib.dom.d.ts あたりに LaunchQueue
の型定義が入ったらこの定義は要らなくなるでしょう。
拡張子に関連付けて開かれたときのコールバックを window.launchQueue?.setConsumer()
で登録します。コールバックに渡される files
は FileSystemHandle
の配列ですが、現状のスペックを見た感じでは FileSystemDirectoryHandle
が来ることはなく、 FileSystemFileHandle
の配列になりそうです。
コールバックが呼ばれたらファイルを読み込んで好き放題やりましょう。
アプリ登録
Web アプリを Chrome / Edge のアプリとして登録します。登録しないと拡張子に関連付けられません。
- Chrome の場合
- タテ 3 点メニューから[その他のツール]>[ショートカットを作成]を選びます。
- 登録済みアプリを確認(および権限管理や削除など)するにはアドレスバーに
chrome://apps
を打ち込みます。
- Edge の場合
- ヨコ 3 点メニューから[アプリ]>[このサイトをアプリとしてインストール]を選びます。
- 登録済みアプリを確認(および権限管理や削除など)するにはメニューから[アプリ]>[アプリの管理]を選びます。
登録できたら、マニフェストで指定した拡張子のファイルを Windows のエクスプローラーや Mac の Finder から開いてみましょう。当該拡張子のファイルのコンテキストメニューから、 Windows なら[プログラムから開く]、 Mac なら[このアプリケーションで開く]を選ぶことで、 Web アプリのアイコンと名前が出てきて開くことができます。ネイティブアプリケーションと同様、ファイルのダブルクリックで開くデフォルトアプリにもできます。
これ Electron でも Tauri でも Neutralinojs でもないただの Web ページですよ! 派手な機能でしょ?
Mac の Edge でエラー
Mac の Edge でアプリ登録してファイルを開いてみると、ファイルアクセスできませんでした。
Uncaught (in promise) DOMException: The requested file could not be read, typically due to permission problems that have occurred after a reference to a file was acquired.
Windows の Edge や Mac の Chrome では再現しませんでした。 Mac の Edge でも 1 度は開けたような… (私はまだこれを修正すべく戦っていません、まだこの機能が一般に出たばかりなので、もしかしたら Edge のバグでそのうち修正されるかもと期待してます…)
いじったアプリ
- DXF Explorer
https://github.com/dxfom/explorer
参考
(読んだとは言ってない)
- アーティクル
- プログレッシブ Web Appsでファイルを処理する – Microsoft Edge Development | Microsoft Docs
https://docs.microsoft.com/ja-jp/microsoft-edge/progressive-web-apps-chromium/how-to/handle-files - Let installed web applications be file handlers
https://web.dev/file-handling/
- プログレッシブ Web Appsでファイルを処理する – Microsoft Edge Development | Microsoft Docs
- 仕様・設計
- file-handling/explainer.md at main · WICG/file-handling
https://github.com/WICG/file-handling/blob/main/explainer.md - Design Doc: File Handling – Google ドキュメント
https://docs.google.com/document/d/1SpLwK0sQ3CUuuG-T9pFBqlm1Ae-OGwi4MsP5X2bCBow - File Handling – Security Model – Google ドキュメント
https://docs.google.com/document/d/1pTTO5MTSlxuqxpWL3pFblKB8y8SR0jPao8uAjJSUTp4 - Manifest Incubations #file_handlers
https://wicg.github.io/manifest-incubations/index.html#file_handlers-member
- file-handling/explainer.md at main · WICG/file-handling
- Chrome Platform Status
- File Handling – Chrome Platform Status
https://chromestatus.com/feature/5721776357113856
- File Handling – Chrome Platform Status
- デモ
- PRY File Handling Demo
https://principled-ring-yarrow.glitch.me/
- PRY File Handling Demo
その他の記事
Other Articles
関連職種
Recruit