やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

JSのFile System Access APIを使う

 ローカルのファイルを読書できる。

成果物

やったこと

課題

  • ファイル削除
  • ディレクトリ作成・削除
  • ドラッグ&ドロップ

情報源

API

名前

 かつてはNative File System APIという名前だったっぽい。

動作環境

 最新Chromeでないと動作しない。2021/01/15時点。

類似品

API ダメ
FileSystem API サンドボックス。実際のファイルシステムにはアクセスできない
File API 読込のみ。書込できない。

File System Access API

 File System Access APIは、ローカルのファイルシステムを読み書きする。ただしセキュリティの観点から、ファイルアクセスの許可(パーミッション)をユーザに求める仕様である。許可はダイアログで行う。

API 概要 確認ダイアログ
showOpenFilePicker() ファイルを開く(読) 上書き時に出るdialog_3_save.png
showSaveFilePicker() ファイルを開く(読書) (なし)
showDirectoryPicker() ディレクトリを開く 開くときに出るdialog_7_dir_read.png

開く

 ファイルを開くときは以下のようなUIで開かねばならない。ファイルパスを文字列で指定して開くことはできない。

showOpenFilePicker.png

上書き

 上書きはFileSystemFileHandle.createWritable()で行う。showOpenFilePicker()で開いたファイルを上書きする。

 showOpenFilePicker()で開いたファイルは書込許可がない。もし上書き保存しようとしたら以下の確認ダイアログでパーミッションを与えねばならない。この手続きは省略できないようだ。

dialog_3_save.png

パーミッションのライフ期間

 パーミッションはブラウザを閉じるまで保存される。ブラウザを閉じたあとでページを開くと、再びダイアログでパーミッションを与えねばならない。

 IndexedDBでパーミッションを保存できる。

  1. 最後に書き込んだファイルハンドラをIndexedDBで書き込む
  2. ページ読込時にIndexedDBに保存されたファイルハンドラを読み込む
  3. 以後、上書き保存しても確認ダイアログが出ない

 ユーザは上書きするとき、1度だけ確認ダイアログで許可を出す。その後はIndexedDBで保存されているかぎり、ブラウザを閉じても確認ダイアログが出ない。その動きは以下で確認できる。

別名で保存する

 別名で保存する。このときも開くとき同様だ。ファイル選択ダイアログでファイルを指定せねばならない。タイトルがファイルを保存となっている点が異なる。

showSaveFilePicker.png

 showSaveFilePicker()で開いたファイルハンドラは書込許可がついた状態である。上書き保存するときに確認ダイアログは出ない。

ディレクトリを開く

 showDirectoryPicker()を使う。ファイルを開くときと同様だ。タイトルがフォルダを選択となっている点が異なる。

showDirectoryPicker.png

 開くとき、以下の確認ダイアログが表示される。これも回避する手段はなさそう。未確認だが、上書き時に用いたIndexedDBにファイルハンドルを保存する方法で二回目以降の確認ダイアログを省略できると思われる。

dialog_7_dir_read.png

所感

すごい!

 嬉しい。ついにブラウザからローカルファイルを操作できるようになった。これをもうずっと前からやりたかった。APIを実装してくれた偉い人たちに感謝。

セキュリティのせいで面倒

 あらゆる手順が面倒くさい。electronとか使ったほうが楽かも? 未調査のため不明。

ファイル選択がウザい

 超うざい。手動での操作が必須って……。クソすぎ。

パス取得が超めんどう

  1. ディレクトリを選択: showDirectoryPicker()
  2. ファイルを選択: showOpenFilePicker()
  3. 1のハンドラで2のハンドラとの相対パスを取得: 7/main.js#L19

 ファイルからフルパスが見れたら楽だったのに。

対象環境

$ uname -a
Linux raspberrypi 5.4.83-v7l+ #1379 SMP Mon Dec 14 13:11:54 GMT 2020 armv7l GNU/Linux