JavaScript | Web API:ファイル・データ操作 - URL.createObjectURL

JavaScript JavaScript
スポンサーリンク

URL.createObjectURL は「Blob や File に一時的な URL を貼る魔法」

URL.createObjectURL は、
BlobFile に「一時的にアクセスできる URL」を発行する関数 です。

普通、<img src="..."><a href="..."> には
https://... みたいな「サーバー上の URL」を入れますよね。

でも、ブラウザの中だけで作ったデータ(Blob)や、
ユーザーが選んだローカルファイル(File)には、
そんな URL は最初から存在しません。

そこで、

「この Blob / File を指す“仮の URL”をブラウザに作ってもらう」
「その URL を img.src や a.href にセットして使う」

ということを可能にするのが URL.createObjectURL です。

この URL はブラウザの中だけで有効な「一時的な URL」で、
ページを閉じたり URL.revokeObjectURL を呼ぶと無効になります。


基本形:Blob / File → createObjectURL → href / src にセット

シグネチャと戻り値

const url = URL.createObjectURL(blobOrFile);
JavaScript

引数には BlobFile を渡します。
戻り値は文字列の URL です。

例:

"blob:https://example.com/2f0c1c2b-...."
JavaScript

この URL を、
<img>src<a>href にそのまま使えます。

重要ポイント:URL の中身は「ブラウザが管理している」

createObjectURL が返す URL は、
サーバーに存在するわけではありません。

ブラウザが内部的に
「この URL が来たら、この Blob / File の中身を返す」
という対応表を持っているイメージです。

だからこそ、

ネットワークに出ていかない
ローカルファイルでもプレビューできる
メモリを使うので、使い終わったら解放したほうがよい

という性質を持ちます。


例題①:File から画像プレビューを表示する

HTML

<input type="file" id="fileInput" accept="image/*">
<img id="preview" alt="プレビュー" style="max-width: 200px;">

JavaScript

const input = document.querySelector("#fileInput");
const img = document.querySelector("#preview");

input.addEventListener("change", () => {
  const file = input.files[0];
  if (!file) return;

  const url = URL.createObjectURL(file);
  img.src = url;
});
JavaScript

流れを整理すると、

ユーザーが画像ファイルを選ぶ → File を受け取る
URL.createObjectURL(file) で一時 URL を作る
その URL を img.src にセットする

これだけで、
ローカルの画像ファイルをアップロードせずにプレビューできます。

ここで掴んでほしいのは、

「File をそのまま img.src に渡せるわけではない」
「File → URL.createObjectURL → src という橋渡しが必要」

という感覚です。


例題②:Blob からテキストファイルをダウンロードさせる

HTML

<button id="download">テキストをダウンロード</button>

JavaScript

const btn = document.querySelector("#download");

btn.addEventListener("click", () => {
  const text = "こんにちは\nこれは Blob から作ったテキストファイルです。";

  const blob = new Blob([text], { type: "text/plain" });

  const url = URL.createObjectURL(blob);

  const a = document.createElement("a");
  a.href = url;
  a.download = "sample.txt";
  a.click();

  URL.revokeObjectURL(url);
});
JavaScript

ここでの流れは、

文字列から Blob を作る
Blob に対して createObjectURL で一時 URL を作る
<a>href にその URL をセットし、download でファイル名を指定
a.click() で擬似クリックしてダウンロード開始
最後に URL.revokeObjectURL(url) で URL を解放

というものです。

URL.createObjectURL がなければ、
「ブラウザ内のデータをファイルとしてダウンロードさせる」のはかなり面倒です。

ここでの重要ポイントは、

「Blob を“ダウンロード可能なファイル”に変える鍵が createObjectURL」

ということです。


重要ポイント:FileReader との違いをはっきりさせる

FileReader は「中身を取り出す」、createObjectURL は「URL を貼る」

よく混ざるのが FileReader との違いです。

FileReader:

ファイルや Blob の中身を
文字列(readAsText)
data URL(readAsDataURL)
ArrayBuffer(readAsArrayBuffer)

として「取り出す」ためのもの。

URL.createObjectURL:

ファイルや Blob に
「一時的にアクセスできる URL を貼る」ためのもの。
中身を自分で読むわけではない。

例えば画像プレビューなら、
どちらでも実現できます。

FileReader 版:

const reader = new FileReader();
reader.onload = () => {
  img.src = reader.result; // data URL
};
reader.readAsDataURL(file);
JavaScript

createObjectURL 版:

const url = URL.createObjectURL(file);
img.src = url;
JavaScript

どちらも正解ですが、

FileReader は「中身を JS で扱いたいとき」
createObjectURL は「URL として扱えれば十分なとき(img.src, a.href など)」

という使い分けをするとスッキリします。


重要ポイント:URL.revokeObjectURL で「後片付け」をする

なぜ解放が必要なのか

URL.createObjectURL で作られた URL は、
ブラウザ内部に「URL → Blob / File」の対応が保持されます。

これを放置し続けると、
メモリを無駄に使い続けることになります。

そこで、
「もうこの URL は使わない」
となったタイミングで URL.revokeObjectURL(url) を呼びます。

const url = URL.createObjectURL(blob);
// 使い終わったら
URL.revokeObjectURL(url);
JavaScript

小さなアプリや短時間の利用では
そこまでシビアにならなくても動きますが、
長時間動くアプリや大量の Blob を扱う場合は、
きちんと後片付けする癖をつけておくと安心です。

いつ revoke すべきかの目安

画像プレビューの場合:

画像を表示し続けるなら、その間は URL が必要
画像を差し替えるとき、古い URL を revoke する

ダウンロードの場合:

a.click() でダウンロードを開始した直後に revoke して OK
ユーザーのダウンロードは既に始まっているので問題ない

ざっくり言えば、
「その URL を参照する要素がもう存在しないタイミング」で
revoke すれば大丈夫です。


例題③:複数画像のプレビューと URL の解放

HTML

<input type="file" id="fileInput" accept="image/*" multiple>
<div id="preview"></div>

JavaScript

const input = document.querySelector("#fileInput");
const preview = document.querySelector("#preview");

// 以前の URL を覚えておく
let urls = [];

input.addEventListener("change", () => {
  // 古いプレビューと URL を片付ける
  preview.innerHTML = "";
  urls.forEach(url => URL.revokeObjectURL(url));
  urls = [];

  Array.from(input.files).forEach(file => {
    const url = URL.createObjectURL(file);
    urls.push(url);

    const img = document.createElement("img");
    img.src = url;
    img.style.maxWidth = "100px";
    img.style.marginRight = "8px";

    preview.appendChild(img);
  });
});
JavaScript

ここでのポイントは、

新しいファイルを選ぶたびに
古い <img> を消し、古い URL を revoke している

というところです。

これで、
「プレビューを更新するたびにメモリが増え続ける」
という状態を防げます。


初心者として URL.createObjectURL で本当に掴んでほしいこと

URL.createObjectURL は「Blob / File に一時的な URL を貼る」ための関数
その URL は img.src や a.href にそのまま使える
FileReader は「中身を取り出す」、createObjectURL は「URL として扱う」ため、と役割が違う
作った URL はブラウザが内部で Blob / File と紐づけて管理している
使い終わったら URL.revokeObjectURL(url) で解放するのが望ましい

まずは、

画像ファイルを選んで createObjectURL でプレビューする
文字列から Blob を作って createObjectURL 経由でダウンロードさせる

この 2 パターンを自分で書いてみてください。

「ローカルのファイルやメモリ上のデータが、
一瞬だけ“URL を持った存在”になる」
という感覚が一度でも掴めると、
URL.createObjectURL はただの関数ではなく、
「ブラウザ内のデータと、URL ベースの世界をつなぐ小さなゲート」 に見えてきます。

タイトルとURLをコピーしました