HTMLファイルをダブルクリックして開いたら、画像が読み込めない。コードは正しいのに、エラーが出る。
この現象、プログラミングを始めたばかりの人がほぼ全員ハマります。原因はコードではなく、ブラウザのセキュリティの仕組みにあります。
この記事では図を使って「なぜそうなるのか」「どうすれば動くか」を順番に説明します。
ブラウザが画面を表示するまでの流れ
まず「ブラウザ」の話から始めます。ブラウザとは、ChromeやSafari、Firefoxなどのことです。
ブラウザがWebページを表示するとき、裏側でこういうことが起きています。
ページを開くたびに、ブラウザはどこかのサーバーからデータをもらっています。これが通常の流れです。
ダブルクリックで開くと何が違うのか
プログラミングの練習では、自分で書いたHTMLファイルをダブルクリックして確認することがあります。このとき、先ほどと流れが変わります。
URLバーを見ると file:///Users/yourname/Desktop/index.html のような表示になっています。https:// ではなく file:// で始まっているのが目印です。
サーバーを経由していないため、「どこからもらったデータか」がブラウザに伝わりません。
なぜ画像が読み込めなくなるのか
ブラウザには「どこからもらったデータか」を確認するセキュリティの仕組みがあります。この「どこからもらったか」を、専門用語でオリジンと呼びます。
file:// で開いたページは「どこから来たか不明」扱いになります。
不明だとなぜ困るのか
「出所不明のファイル」がパソコン内を自由に読み書きできたら、こんな事故が起きます。
ファイルを開いただけで、パソコン内の情報が盗まれます。
これを防ぐために、ブラウザは file:// からのファイル読み込みを制限しています。制限はバグではなく、あなたを守るための設計です。
実際に出るエラー
画像をCanvasに描いてピクセルデータを取得しようとするコードを例にします。
const img = new Image();
img.src = './images/photo.png';
img.onload = () => {
ctx.drawImage(img, 0, 0);
const data = ctx.getImageData(0, 0, 100, 100); // ここでエラー
};
「画像は表示できるのに読み取れない」のは、表示とデータ取得が別のルールで動いているためです。表示はオリジン不問で許可されていますが、データの取り出しはオリジンの確認が必要になります。
エラーメッセージに出てくる「CORS」「tainted」「null」は、どれもこの制限を指しています。
解決方法
方法1: VS CodeのLive Server拡張を使う(まずこれを試す)
ローカルサーバーとは、自分のパソコンの中で動く小さなサーバーです。これを使うと http://localhost:5500 というURLでページが開き、オリジンが確定して制限がなくなります。
コマンドは不要です。VS Codeの拡張機能「Live Server」を入れると、右クリックだけで起動できます。
手順はこれだけです。
- VS Codeの拡張機能タブで「Live Server」を検索してインストール
- HTMLファイルを右クリック
- 「Open with Live Server」を選ぶ
- ブラウザが自動で開いて
http://localhost:5500で表示される
ファイルを保存するたびにブラウザが自動で更新されるので、開発中の確認にも便利です。
方法2: ファイル選択ボタンを使う
ユーザー自身がファイルを選ぶ操作を挟む方法です。「自分で選んだ」という操作があれば、ブラウザが読み取りを許可します。
HTMLにこの1行を追加します。
<input type="file" id="fileInput">
サーバーなしで動きますが、毎回ファイルを選ぶ手間がかかります。
方法3: Electron などを使う(上級者向け)
配布用のデスクトップアプリとして作るなら、Electronというツールが選択肢になります。ブラウザの制限の外でファイルを読む仕組みを持っているため、file:// の制約を受けません。
ただし環境構築が必要で学習コストが上がります。まずは方法1から試してみてください。
まとめ
| やりたいこと | 方法 |
|---|---|
| まず動かしたい | VS CodeのLive Server拡張 → index.htmlを右クリック → Open with Live Server |
| サーバーなしで動かしたい |
<input type="file"> でファイルを選ばせる |
| アプリとして配布したい | Electron を検討する |
エラーに null や CORS や tainted が出たら、この記事の話です。