この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:4
ページ更新者:guest
更新日時:2026-06-11 07:07:02

タイトル: File API
SEOタイトル: Web File API 完全ガイド|File/Blob/FileReader/Drag&Drop/File System Access

この記事の要点
  • File API はブラウザ上でローカルファイルを安全に扱う Web 標準
  • 主要オブジェクト: File / FileList / Blob / FileReader / URL.createObjectURL
  • 読み取り: readAsText / readAsDataURL / readAsArrayBuffer
  • 入力: / Drag & Drop / Clipboard
  • モダン: File System Access API (Chrome) で読み書き可能、IndexedDB と連携

File API とは

File API は、ブラウザ JavaScript からローカルファイルを安全に読み書きするための W3C / WHATWG 標準 API 群です。同一オリジンポリシーやユーザー操作(クリック・ドロップ)を起点とする原則により、ユーザーの明示的な許可なしに任意ファイルにアクセスできない設計です。

関連仕様: File API / FileReader API / HTML5 Drag and Drop API / File System Access API / Streams API

基本オブジェクト

オブジェクト説明
Blob任意バイナリデータ。サイズ・MIME を持つ
FileBlob の拡張、ファイル名・最終更新日を追加
FileListFile の配列 (input.files / DataTransfer.files)
FileReaderファイルを非同期で読み取るリーダ
URL.createObjectURLBlob/File を一時 URL に変換 (img/video 等で使用)
FormDatamultipart/form-data として fetch でアップロード

ファイル選択 (input type=file)


属性説明
acceptMIME や拡張子で制限 (例: image/*,.pdf)
multiple複数選択許可
captureモバイルでカメラ起動 (user / environment)
webkitdirectoryディレクトリ単位選択 (Chromium/Firefox)

FileReader で内容を読む

const reader = new FileReader();

// テキストとして読む
reader.onload = () => console.log(reader.result);
reader.readAsText(file, 'UTF-8');

// データ URL (Base64) として読む → img.src へ
reader.onload = () => document.getElementById('img').src = reader.result;
reader.readAsDataURL(file);

// ArrayBuffer として読む (バイナリ操作)
reader.onload = () => {
  const buf = reader.result;
  const view = new Uint8Array(buf);
  console.log('first 4 bytes:', view.slice(0, 4));
};
reader.readAsArrayBuffer(file);

// 進捗・エラー
reader.onprogress = (e) => {
  if (e.lengthComputable) console.log((e.loaded / e.total * 100).toFixed(1) + '%');
};
reader.onerror = () => console.error(reader.error);

// 中断
reader.abort();

モダンな書き方 (await + File メソッド)

// File は自身にメソッドを持つ (modern browsers)
const text = await file.text();
const buffer = await file.arrayBuffer();
const stream = file.stream();   // ReadableStream

// 巨大ファイルをチャンク処理
const reader = file.stream().getReader();
while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  console.log('chunk', value.byteLength);
}

URL.createObjectURL で表示

const url = URL.createObjectURL(file);
document.getElementById('preview').src = url;

// 不要になったら解放 (メモリリーク防止)
img.onload = () => URL.revokeObjectURL(url);

Drag & Drop

ここにファイルをドロップ

クリップボード経由

// 貼り付けイベントから画像取得
document.addEventListener('paste', async (e) => {
  for (const item of e.clipboardData.items) {
    if (item.type.startsWith('image/')) {
      const file = item.getAsFile();
      console.log('pasted image:', file.name, file.size);
    }
  }
});

// クリップボードに書き込み (要 user gesture)
const blob = new Blob(['hello'], { type: 'text/plain' });
await navigator.clipboard.write([new ClipboardItem({ 'text/plain': blob })]);

fetch でアップロード

// FormData (multipart)
const fd = new FormData();
fd.append('upload', file, file.name);
fd.append('title', 'sample');
const res = await fetch('/api/upload', { method: 'POST', body: fd });

// Blob を直接 PUT
await fetch('/api/upload', {
  method: 'PUT',
  body: file,
  headers: { 'Content-Type': file.type },
});

// チャンク分割アップロード
const CHUNK = 5 * 1024 * 1024;   // 5MB
for (let i = 0; i < file.size; i += CHUNK) {
  const chunk = file.slice(i, i + CHUNK);
  await fetch('/api/upload-chunk?offset=' + i, { method: 'POST', body: chunk });
}

ダウンロード (Blob 経由)

function downloadBlob(blob, filename) {
  const a = document.createElement('a');
  a.href = URL.createObjectURL(blob);
  a.download = filename;
  a.click();
  URL.revokeObjectURL(a.href);
}

// CSV をその場で生成してダウンロード
const csv = 'name,score\nAlice,80\nBob,75';
downloadBlob(new Blob([csv], { type: 'text/csv' }), 'scores.csv');

File System Access API (Chrome 系)

従来の File API が読み取り中心なのに対し、File System Access API はユーザーの許可下でローカルファイル/ディレクトリへの書き込みも可能にします (Chromium 系のみ)。

// ファイルを開いて読み書き
const [handle] = await window.showOpenFilePicker({
  types: [{ description: 'Text', accept: { 'text/plain': ['.txt'] } }],
});
const file = await handle.getFile();
console.log(await file.text());

// 同じ場所に書き戻し
const w = await handle.createWritable();
await w.write('updated content');
await w.close();

// ディレクトリ選択
const dir = await window.showDirectoryPicker();
for await (const [name, h] of dir.entries()) {
  console.log(name, h.kind);  // 'file' or 'directory'
}

// 新規ファイル保存
const saveHandle = await window.showSaveFilePicker({
  suggestedName: 'note.txt',
  types: [{ accept: { 'text/plain': ['.txt'] } }],
});
const ws = await saveHandle.createWritable();
await ws.write('hello');
await ws.close();

IndexedDB との連携

Blob は IndexedDB に直接格納できるため、オフラインキャッシュやローカル DB と組み合わせやすい:

const db = await openDB('files', 1, {
  upgrade(db) { db.createObjectStore('store', { keyPath: 'name' }); },
});
await db.put('store', { name: file.name, blob: file });
const saved = await db.get('store', 'photo.jpg');
const url = URL.createObjectURL(saved.blob);

セキュリティ・制限事項

  • 同一オリジンポリシー: ドラッグ元クロスオリジンの blob URL は使えないことがある
  • ユーザー操作起点: showOpenFilePicker / showSaveFilePicker はクリックなど gesture 内でのみ呼び出し可能
  • サイズ制限: ブラウザの IndexedDB / メモリ制限。大容量は Streams API でチャンク処理
  • ファイル名は安全に: アップロード後はサーバ側で正規化 (拡張子強制、ハッシュ名)

ブラウザ対応

APIChromeFirefoxSafari
FileReader / Blob / File
file.text() / arrayBuffer()
Drag & Drop
Clipboard image paste
File System Access××
webkitdirectory

FAQ

Q: Base64 (DataURL) と Blob URL、どちらを使うべき?
A: 表示用には Blob URL。Base64 はメモリ・転送効率が悪い (約 33% 増)。サーバへ JSON 形式で送る必要があるときだけ Base64。

Q: ローカルに自由に書き込めないの?
A: 任意の場所は不可。File System Access API でユーザー許可を得た範囲のみ可能。それ以外は IndexedDB / OPFS (Origin Private File System) を使う。

Q: 巨大ファイル (1GB 超) をアップロードしたい
A: file.slice() でチャンク化し、サーバ側で結合。S3 マルチパートアップロードや tus プロトコルを使うと冪等で堅牢。