【JavaScript】File System Access API – ファイルピッカーを表示してファイルを保存する方法 showSaveFilePicker() 編

ファイル保存ダイアログを表示し、ユーザーに PC やスマートフォン内にファイルを保存するには 2 つの方法あがります。今回は旧来より使われてきた <a download="filename"> を使う方法と、モダンな showSaveFilePicker() を使った方法をそれぞれ解説し、それらの違いについて解説していきます。

<a download=”filename”> を使う方法

a 要素の download 属性を使う方法は、これまで最もポピュラーなファイル保存方法でした。詳細は記事「生成データをファイルとして保存(ダウンロード)させる方法」をご覧頂きたいのですが、ここでは簡単にその方法を紹介します。

<a href="#" id="dllnk" download="test.txt">テキストダウンロード</a>
document.getElementById('dllnk').addEventListener('click', (event) => {
  // テキストファイルを表す Blob オブジェクトを生成
  const text = 'こんにちは。';
  const blob = new Blob([text], { type: 'text/plain' });

  // a 要素の href 属性に Object URL を セット
  event.currentTarget.href = window.URL.createObjectURL(blob);
});

このサンプルでは a 要素の「テキストダウンロード」リンクをクリックすると、a 要素の click イベントのリスナー関数が実行されます。そこでは、動的にテキストデータを Blob オブジェクトとして生成し、a 要素の download 属性にその Object URL をセットしています。

この a 要素の click イベントのリスナー関数の実行が終了すると、a 要素の click イベントのデフォルトアクション実行に移行します。つまり、ファイルダウンロードが行われ、その結果、ファイル保存ダイアログが表示されることになります。

ユーザーの操作が a 要素のクリックならこれで解決しますが、button 要素ならどうでしょう。少し悩みます。詳細は記事「生成データをファイルとして保存(ダウンロード)させる方法」をご覧頂くとして、少々トリッキーな技を使わないといけません。

a 要素の download 属性は、本来は、旧来の一般的なウェブページのリンククリックを通してサーバーにあるファイルをダウンロードさせることを想定したものです。一方で、ウェブアプリケーションでは JavaScript で動的にデータを生成して、それをファイルとして保存させたい場合が多いでしょう。そういったケースを想定して作られたのが showSaveFilePicker() メソッドです。

showSaveFilePicker() メソッドを使う方法

showSaveFilePicker() は、ファイル保存ダイアログを表示して、ユーザーにファイルを保存させるメソッドですが、そのトリガーとなる HTML 要素は、クリックを検知できるなら何でも構いません。

次のサンプルは、button 要素のボタンを押したら showSaveFilePicker() メソッドを使ってファイル保存ダイアログを表示します。ユーザーによって保存ファイルが指定されたら、テキストデータを動的に生成して、指定のファイルにデータを書き込みます。

<button id="btn">ファイルを保存</button>
document.getElementById('btn').addEventListener('click', async () => {
  // ファイル保存ダイアログを表示して FileSystemFileHandle オブジェクトを取得
  const fh = await window.showSaveFilePicker({ suggestedName: 'test.txt' });

  // FileSystemWritableFileStream オブジェクトを取得
  const stream = await fh.createWritable();

  // テキストデータの Blob オブジェクトを生成
  const blob = new Blob(['こんにちは'], { type: 'text/html' });

  // テキストデータをファイルに書き込む
  await stream.write(blob);

  // ファイルを閉じる
  await stream.close();

  // 保存されたファイルのファイル名をコンソールに出力
  console.log(fh.name);
});

この JavaScript のポイントは、ファイル保存ダイアログを表示するところです。showSaveFilePicker() メソッドは window オブジェクトのメソッドです。引数を引き渡していますが、ここでは suggestedName プロパティに test.txt を指定しています。

const fh = await window.showSaveFilePicker({ suggestedName: 'test.txt' });

このコードが実行されると、Windows 11 であれば、次のようなファイル保存ダイアログが表示されるはずです。

ご覧の通り、suggestedName プロパティに指定したファイル名がプリセットされていることが分かります。もちろん、ユーザーはファイル名を変更することができます。suggestedName プロパティに指定したファイル名はあくまでも提案(suggested)に過ぎません。

ここでユーザーが「保存」または「キャンセル」を押すまで、showSaveFilePicker() メソッドは返ってきません。もしユーザーが「キャンセル」を押すと、showSaveFilePicker() メソッドは例外 DOMException を投げます。

ユーザーが「保存」を押すと、showSaveFilePicker() メソッドは指定のファイル名で空のファイルを生成します。既存のファイルを指定すると空にしてしまいます。そして、showSaveFilePicker() メソッドは該当のファイルを表す FileSystemFileHandle オブジェクト(変数 fh)を返します。このオブジェクトを通してファイルデータを書き込む必要があります。

データの書き込みの詳細については、記事「File System Access API – 仮想的なファイルシステム Origin Private File System 編」をご覧ください。

まとめ

2022 年 6 月現在では Chrome, Edge といった Chromium 系ブラウザーは showSaveFilePicker() をサポートしていますが、Safari と Firefox はサポートしていません。せめてスマートフォンでシェアが大きい Safari はサポートしてほしいところです。

今回は以上で終わりです。最後まで読んでくださりありがとうございました。それでは次回の記事までごきげんよう。

Share