ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
| この記事の要点 |
|
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 を持つ |
File | Blob の拡張、ファイル名・最終更新日を追加 |
FileList | File の配列 (input.files / DataTransfer.files) |
FileReader | ファイルを非同期で読み取るリーダ |
URL.createObjectURL | Blob/File を一時 URL に変換 (img/video 等で使用) |
FormData | multipart/form-data として fetch でアップロード |
ファイル選択 (input type=file)
<input type="file" id="picker" accept="image/*" multiple>
<script>
const picker = document.getElementById('picker');
picker.addEventListener('change', (e) => {
const files = e.target.files; // FileList
for (const file of files) {
console.log(file.name, file.size, file.type, file.lastModified);
}
});
</script>
| 属性 | 説明 |
|---|---|
accept | MIME や拡張子で制限 (例: 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
<div id="drop" style="border:2px dashed #888;padding:40px;text-align:center">
ここにファイルをドロップ
</div>
<script>
const drop = document.getElementById('drop');
drop.addEventListener('dragover', (e) => {
e.preventDefault(); // 必須: drop を有効化
drop.style.background = '#eef';
});
drop.addEventListener('dragleave', () => drop.style.background = '');
drop.addEventListener('drop', (e) => {
e.preventDefault();
drop.style.background = '';
const files = e.dataTransfer.files;
for (const f of files) console.log(f.name);
});
</script>
クリップボード経由
// 貼り付けイベントから画像取得
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 でチャンク処理
- ファイル名は安全に: アップロード後はサーバ側で正規化 (拡張子強制、ハッシュ名)
ブラウザ対応
| API | Chrome | Firefox | Safari |
|---|---|---|---|
| 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 プロトコルを使うと冪等で堅牢。
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
子ページはありません
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript base URL 取得方法|window.location.origin と SSR/Node.js 対応
- 4 YouTube Data API v3 エラー一覧|403/400/404 の主要原因と切り分け
- 5 Spring Frameworkのアノテーション一覧
- 6 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 7 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- IPv6とは|128bitアドレス・コロン16進表記/::省略・リンクローカル・SLAAC・デュアルスタック NEW 2026-06-22 12:34:44
- VPNとは|暗号トンネル・サイト間/リモートアクセス・IPsec/SSL-VPN/WireGuardを解説 NEW 2026-06-22 12:19:10
- MAC アドレスフィルタリングの仕組みと限界 | ネットワーク入門 NEW 2026-06-22 12:19:10
- WebRTC とは ブラウザ間 P2P の音声・映像・データ通信 | ネットワーク入門 NEW 2026-06-22 12:17:25
- gRPC とは HTTP/2 + Protocol Buffers の高速 RPC | ネットワーク入門 NEW 2026-06-22 12:17:25
- HTTP/3 (QUIC) とは UDP ベースの低遅延 Web 通信 | ネットワーク入門 NEW 2026-06-22 12:17:25
- HTTP/2 とは 多重化・HPACK・バイナリフレーム | ネットワーク入門 NEW 2026-06-22 12:17:25
- Web通信プロトコル入門 HTTP/2・HTTP/3・WebSocket・gRPC・WebRTC | ネットワーク入門 NEW 2026-06-22 12:17:25
- WebSocket とは 全二重リアルタイム通信 ws/wss | ネットワーク入門 NEW 2026-06-22 12:17:25
- ファイアウォールとは|パケットフィルタ・ステートフル・DMZ・次世代FW(L4/L7)を解説 NEW 2026-06-22 12:17:24
- iptables/nftablesとは|テーブル・チェーン・ルール例・永続化をLinux視点で解説 NEW 2026-06-22 12:17:24
- HAProxy とは frontend/backend と設定例 | ネットワーク入門 NEW 2026-06-22 12:17:24
- 証明書と認証局(CA)とは|X.509・信頼チェーン・DV/OV/EV・失効(CRL/OCSP)を解説 NEW 2026-06-22 12:17:24
- CDN とは エッジキャッシュ・TTL・Cloudflare/CloudFront | ネットワーク入門 NEW 2026-06-22 12:17:24
- TLS/SSLの仕組み|ハンドシェイク・暗号スイート・前方秘匿性・証明書検証をわかりやすく解説 NEW 2026-06-22 12:17:24
コメントを削除してもよろしいでしょうか?