ブラウザでのファイル操作#
WebApp の開発中には、ファイル関連の操作(サーバーへのファイルのアップロード、ローカルへのファイルのダウンロード、ファイルのキャッシュなど)に遭遇することがあります。以下では、ファイル操作を行うためのいくつかの異なる方法を紹介します。
タグベースのアップロードとダウンロード#
最も一般的なファイルのアップロード方法は、input タグを使用することです。input タグの type="file"
を設定することで、ユーザーがローカルからファイルを選択してアップロードすることができます。
function InputFile() {
const [file, setFile] = useState<File | null>(null);
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (!file) return;
setFile(file);
};
return <input onChange={handleChange} type="file" />
}
ファイルアクセス API#
ファイルシステムアクセス API(File System Access API)は、ファイルシステム APIの一部であり、API を使用してユーザーの操作に基づいてファイルの読み書きを行うことができます。
この API を使用してファイル操作を行う場合、以下のインターフェースが使用されます。
- showOpenFilePicker:ファイル選択ダイアログを表示し、ユーザーが 1 つまたは複数のファイルを選択できるようにし、これらのファイルのハンドルを返します。
export function PickerFS() {
const [file, setFile] = useState<File | null>(null);
const handleChooseFile = async () => {
const fileHandles = await window.showOpenFilePicker();
const file = await fileHandles[0].getFile();
setFile(file);
};
return <Button onClick={handleChooseFile}>Click</Button>
}
- showSaveFilePicker:ファイル選択ダイアログを表示し、ユーザーがファイルを保存できるようにします(上書きまたは新規作成)。
export function PickerFS() {
const handleChooseFile = async () => {
const directoryHandle = await window.showDirectoryPicker();
const keys = directoryHandle.keys();
// このディレクトリ内のすべてのファイルの名前を表示する
for await (const key of keys) {
console.log(key);
}
};
return <Button onClick={handleChooseFile}>Click</Button>
}
- showDirectoryPicker:ディレクトリ選択ダイアログを表示し、ユーザーがディレクトリを選択できるようにします。
export function PickerFS() {
const [file, setFile] = useState<File | null>(null);
const handleDownloadFile= async () => {
const opts = {
suggestedName: "test.txt",
types: [
{
description: "Text file",
accept: { "text/plain": [".txt"] },
},
],
};
const fileHandle = await window.showSaveFilePicker(opts);
const writable = await fileHandle.createWritable();
await writable.write("Hello, world!");
await writable.close();
};
return <Button onClick={handleDownloadFile}>Click</Button>
}
オリジンプライベートファイルシステム#
オリジンプライベートファイルシステムは、ファイルシステム API の一部であり、ファイルアクセスシステムと似ていますが、ユーザーからは見えないという最も直接的な違いがあります。showXXX インターフェースはファイル(またはディレクトリ)選択ダイアログを開く必要があり、ユーザーがファイル(またはディレクトリ)を選択する必要があります。保存されるファイルもユーザーが指定したパスに保存する必要がありますが、オリジンプライベートファイルシステムのインタラクションはユーザーには見えず、保存されるファイルは処理されたデータであり、元のデータはユーザーには見えません。
export function OpFs() {
const handleChooseFile = async (event: React.ChangeEvent<HTMLInputElement>) => {
const fileList = event.target.files;
const file = fileList && fileList[0];
if (!file) return;
const opfsRoot = await navigator.storage.getDirectory();
const fileHandle = await opfsRoot.getFileHandle(file.name, { create: true });
const writable = await fileHandle.createWritable();
await writable.write(file);
await writable.close();
};
return <InputFile onChange={handleChooseFile} />;
}
await navigator.storage.getDirectory()
は、ユーザーのローカルファイルシステムのルートディレクトリを表すファイルハンドルを返し、getFileHandle
を使用して指定したファイルのハンドルを取得します。create が true の場合、ファイルが存在しない場合には作成されます。その後、createWritable
を使用して書き込み可能なストリームを作成し、開発者はこのストリームを使用して指定したファイルにデータを書き込むことができます。最後に、書き込み可能なストリームを閉じます。
注意事項#
関連情報#
- https://web.dev/articles/origin-private-file-system?hl=ja#specifics_of_the_origin_private_file_system
- https://developer.chrome.com/docs/capabilities/web-apis/file-system-access?hl=ja
- https://gine.me/posts/70f8e931bc17426fb54127948bcf4a0e
- https://hughfenghen.github.io/posts/2024/03/14/web-storage-and-opfs/