#070
posted on 2022.04.08 (Fri) 2023.11.10 (Fri)

Blobの基礎知識。

サーバーにあるファイルや、PCなどクライアント内のローカルファイルなどをバイナリーデータとして、JavaScriptのBlobを利用してブラウザ上で扱うための基礎知識のメモ。

※ バイナリーデータの基礎知識は前の記事を参照。

 

 

Blob

(1) Blob

「Blob」(Binary Large Object)とは、データベース管理システムで用いられるデータ型のひとつ。
通常のデータ型のフィールドには格納できない、画像、動画、プログラムなどのバイナリーデータを格納するための型として使われる。のちにJavaScriptでも実装される。

※ 名称の由来は「The Blob」という1950年代の映画らしい。(Rottento Matoes。)

 

(2) JavaScriptにおけるBlob

JavaScriptでの「Blob」は、「File API」の中で定義されている「Blob」オブジェクトのことを指す。

データベース管理システムでのBlobと同様にバイナリーデータを扱うためのもの。

※ File APIについてのW3Cの公式ドキュメント

  • 「File API」とは、JavaScriptによってPC内のローカルファイルにアクセスするためのAPI。
  • 「Blob」を生成または取得すると、ブラウザは内部的にメモリ上にバイナリーデータを保持する。
  • 「Blob」はバイナリーデータなので、テキストファイル以外にも画像や動画など様々な形式のファイルを扱うことができる。
  • 「Blob」のデータは、ダウンロードしたりアップロードしたりすることができる。
  • 「Blob」はimmutable(不変)で、その中身を直接変更することはできない。(一部を抽出、切り貼りなどして新しいBlobの生成はできる。)
  • 「URLスキーム」(「Blob URL Scheme」)を利用して、「Blob」(Blobオブジェクトが参照しているバイナリーデータ)へのURLを生成することができる。(「URLスキーム」は後述。)
  • 「Blob URL Scheme」のURLは、「Blob」の実体(ブラウザが一時的にメモリに保持しているバイナリーデータ)にアクセスするURLなので、クライアントサイドでJavaScriptが実際に動作しているデバイスでのみ有効なURL。
  • 「Blob URL Scheme」のURLをHTML要素(<a>タグ、<img>タグなど)の属性値に動的に設定することで、「Blob」の実体を表示したりダウンロードしたりすることができる。

 

 

Blobオブジェクト

(1) Blobオブジェクト

「Blob」オブジェクトとは、ブラウザが内部的にメモリ上に保持しているバイナリーデータを参照するオブジェクト。

※ BlobについてのMozillaの公式ドキュメント

    • 「Blob」オブジェクトは、参照しているデータの種類を表す「コンテンツタイプ情報」と「データそのものの情報」によって構成される。
    • 「コンテンツタイプ情報」の部分は、通常は「MIMEタイプ」で指定される。(「image/png」など。)
    • 「データ情報」の部分は、「バッファーのデータ」、「文字列」、「他のBlobオブジェクト」のいずれか(または組み合わせ)で構成される配列が指定される。
    • 「コンテンツタイプ情報」で「ファイル形式」が特定でき、「データ情報」でその実体である「バイナリーデータ」の内容が参照できる。
    • 「コンテンツタイプ情報」を通信リクエストの「Content-Type」として利用できるので、「Blob」のデータのダウンロードやアップロードをすることができる。
    • Blob以外のオブジェクトやデータから「Blob」オブジェクトを作成するには、Blob()コンストラクターを使用する。
    • PCなどクライアント側のシステム内にあるローカルファイルを参照する「Blob」オブジェクトを取得するには「File API」を使用する。(この場合は「File」オブジェクトとして扱う。)
    • 「File」インターフェイスは「Blob」がベースになっていて、「Blob」の機能を継承している。(「File」オブジェクトは、特別な種類の「Blob」オブジェクトで、「Blob」が利用できる場面ではどこでも利用できる。)

 

(2) Blob()コンストラクター

Blob()コンストラクターは、新たなBlobオブジェクトを生成して返す。生成されたBlobオブジェクトの中身は、引数で与えられた値を連結したもので構成される。

※ Blob()コンストラクターについてのMozillaの公式ドキュメント

 

[ Blobオブジェクトを生成する例 ]

Blob()コンストラクターで、内容が「hello world」というテキストデータのBlobオブジェクトを生成する例。

  1. new演算子を付加し、引数に「データの配列」と「コンテンツタイプ」を指定してBlob()コンストラクターを呼び出す。(引数で与えられた配列を連結したものでデータの中身が構成される。)
  2. Blobオブジェクトが生成され、指定したデータ内容のバイナリーデータが内部的にメモリに保持される。
let ag2blob = new Blob(['hello', ' ', 'world'], {type: 'text/plain'});

//sizeプロパティーでデータの総バイトサイズを確認
console.log(ag2blob.size);
//出力されるコンソールの内容
//11

//typeプロパティーでデータのコンテンツタイプを確認
console.log(ag2blob.type);
//出力されるコンソールの内容
//text/plain

new Blob([データの配列], オプション) : 引数で指定した内容で新しく作成されたBlobオブジェクトを返す。第1引数にファイルの内容となるデータの配列、第2引数にファイルの種類となるMIMEタイプを指定する。(第1引数は配列である必要がある。)

  • データの配列 : 「バッファーのデータ」(ArrayBuffer)、「文字列」(USVString)、「他のBlobオブジェクト」(Blob)のいずれか(または組み合わせ)を配列で指定。
  • オプション : 任意で以下の2つのオプションが指定できる。省略可。
    type : 設定したデータの「MIMEタイプ」を指定。(既定値は空文字。)
    endings : データがテキストの場合、現在のOSの改行文字(「\r\n」か「\n」)を変換するかどうか。既定値は「transparent」で「改行文字を変換しない」。「native」で「変換する」にすることもできる。

Blob.size : 指定したBlobオブジェクトに含まれるデータのサイズ(バイト単位)を返す。

Blob.type : 指定したBlobオブジェクトに含まれるデータのMIMEタイプを示す文字列を返す。タイプが不明な場合は空文字を返す。

 

 

Blob URL Scheme

(1) Blob URL Scheme

「Blob URL Scheme」とは、「URLスキーム」に「blob:」が設定されたURLのこと。

※ オブジェクトを表すURLなので「オブジェクトURL」とも呼ばれる。

URIスキーム (URLスキーム)

「URIスキーム」(URLスキーム)とは、URI / URLの先頭部分に位置する「http:」や「ftp:」や「mailto:」などのことで、アクセス先に到達するための手段を明示するもの。(IT用語辞典)

 

  • 「Blob URL Scheme」は、Blob(ブラウザが内部的に保持しているバイナリーデータ)へのアクセス先をURLとして示す。
  • 「Blob URL Scheme」は、「Blob」オブジェクトや「File」オブジェクト(ローカルファイルを使用するオブジェクト)から生成することができる。
  • 「Blob URL Scheme」のURLは、「blob:サイトのドメイン/ランダムな固有の文字列」(「blob:<origin>/<uuid>」)という形式の一意なURLで表される。
  • 「Blob URL Scheme」は、「ランダムな固有の文字列」が使用されるので、ユーザーのディレクトリ名は開発者側に漏洩しない。
  • HTMLコード内のURLを設定できる場所には、「Blob URL Scheme」のURLを設定できる。(<a>ダグのhref属性や<img>タグのsrc属性など。)
  • 「Blob URL Scheme」は静的には用意できず、JavaScriptから動的に生成する必要がある。(静的に用意したい場合は「Data URL Scheme」を使用する。後述。)
  • 生成された「Blob URL Scheme」のURLの寿命は、それを作成したウィンドウの「document」と結び付けられている。(現在の「document」内のみ、かつドキュメントを開いている間のみ有効。)
  • 内部処理で「Blob URL Scheme」がBlobにマッピングされるので、「document」がアンロードされるまでBlobはメモリに常駐し、アンロードされたときに自動的に解放される。(現在のページがアンロードされると自動的に「Blob URL Scheme」がクリアされるので、Blobもメモリ解放される。)
  • 「revokeObjectURL()」メソッドを使って、「Blob URL Scheme」のマッピングによる参照を明示的に削除し、Blobをメモリ解放することができる。(他からBlobを参照しているものがあれば解放されない。)
  • 「revokeObjectURL()」メソッドで明示的に削除するとマッピングされなくなるので、HTML要素の属性値に設定した「Blob URL Scheme」のURLも失効して機能しなくなる。

 

(2) Blob URL Schemeの生成

「Blob URL Scheme」を生成するには、「URL」インターフェイスが持つ「createObjectURL()」メソッドを使用する。

  • オブジェクトURLを生成するための引数に指定できるのは、「Blob」オブジェクト、「File」オブジェクト、「MediaSource」オブジェクトのいずれか。
  • ブラウザは、生成されたオブジェクトURLによるBlobへのマッピングを内部的に格納する。
  • 「revokeObjectURL()」メソッドで破棄しない限り、URLへの参照が切れないのでガベージコレクションの対象にならずメモリに常駐する。(破棄しなくてもページがアンロードされれば自動的に解放される。)

 

[ Blob URL Schemeを生成する例 ]

「window.URL.createObjectURL()」メソッドで「Blob URL Scheme」を生成する例。

  1. 引数に任意のBlobオブジェクトを指定。
  2. 指定したBlobのオブジェクトURLが生成される。(「blob:固有のURL」の形式の文字列を返す。)

※ Webブラウザ上でwindowオブジェクトはグローバルオブジェクトなので、「window.」は省略できる。

let ag2blobUrl = URL.createObjectURL(ag2blob);

//使用後に破棄する場合(メモリから解放されマッピングも削除される)
URL.revokeObjectURL(ag2blobUrl);

window.URL.createObjectURL(オブジェクト) : 指定したオブジェクトを表すオブジェクトURLの文字列(DOMString)を生成して返す。

window.URL.revokeObjectURL(オブジェクトURL) : 指定したオブジェクトURL(URL.createObjectURL()メソッドで生成された既存のオブジェクトURL)を解放する。(マッピングも削除されるのでURLは機能しなくなる。)

 

 

Data URL Scheme

「Blob URL Scheme」とは別の形式の「Data URL Scheme」を使用してBlobなどのバイナリーデータを扱う方法。

※ 「Blob URL Scheme」はBlob(メモリ上のデータ)の実体へアクセスするためのURLで、「Data URL Scheme」はバイナリーデータ(バイト列)そのものを文字列にエンコードし、その文字列をURLの記述が可能な箇所に記述したもの。

※ Blobを「Data URL Scheme」に変換する場合は、「FileReader」オブジェクトの「readAsDataURL()」メソッドを使う。(後述。)

※ データURLについてのMozillaの公式ドキュメント

※ 「Data URL Scheme」は仕様書(RFC 2397)によって定義されているが、WHATWG(W3Cに代わって現在のWeb技術の標準仕様の策定を行っている団体)のFetch Standardで改めて定義されている。

 

(1) Data URL Scheme

「Data URL Scheme」とは、URLスキームに「data:」が設定されたURLのことで、「バイナリーデータ」そのものをURLとして使用できる文字列に変換して記述したもの。

  • 「Data URL Scheme」は、文字列に変換した「バイナリーデータ」をHTMLにインラインで埋め込むことができる。(ただの文字列なので、実体ファイルを読み込む通信は発生しない。)
  • ブラウザは、データURLとして記述された文字列を解析して、バイナリーに複合して使用する。
  • 「Data URL Scheme」は、「Blob URL Scheme」とは違い、静的にも用意できる。
  • 「Data URL Scheme」のURLは、「data:MIMEタイプ;データの書式,データの文字列」(「data:[<mediatype>][;base64],<data>」)という形式で表される。
  • データとして記述できるのは、データのバイト列を「ASCII」形式で表現した文字列。
  • データが「テキスト」で、「ASCII」形式の「SP」(「空白文字」、16進数表記で「0x20」)から「~」(16進数表記で「0x7e」)までの範囲内の文字の場合はそのまま記述できる。
  • データが「テキスト」で、上記の範囲外の場合は更にURLエンコード(パーセントエンコード)してから記述する。(「Percent-encoding」についてのMozillaの公式ドキュメント。)
  • データが「テキスト」でない「バイナリーデータ」の場合は、データを「Base64」エンコードして「ASCII」形式の文字列に変換してから記述する。
  • 「Data URL Scheme」に記述できるように変換した後の文字列のサイズは、元データでのサイズよりも必ず大きくなるので、ファイルサイズが100MBを超える場合は採用しない方が良いとされる。(小さいファイルサイズでもかなり長い文字列になる。)

[ Base64の概要 ]

  • 「Base64」とは、バイナリーデータを64進数表現に変換することで「ASCII」形式の文字列にするエンコード方法。
  • 64種類の英数字のみを用いることで、それ以外の文字は扱うことが出来ない通信環境でもマルチバイト文字やバイナリーデータを扱えるようにするもの。(メールに添付するデータ、ベーシック認証の認証文字列、Data URLなどで主に使用される。)
  • エンコードによる変換には、「A-Z」、「a-z」、「0-9」の62種類の文字、「+」と「/」の2種類の記号が使用され、変換時にパディング(字詰め)が必要な場合は「=」で埋められる。(変換用の64文字と、パディング用の「=」で、実際には65種類の文字が使用される。)

※ 「Base64」のエンコード方式はいくつか種類があるようなので、URLに使用できる文字列に変換するエンコード方式を使う。

 

(2) Data URL Schemeの記述方法

  1. 「URLスキーム」を指定する記述。(必須。)
    「Data URL Scheme」のURLスキームである「data:」を最初に記述。
  2. 「コンテンツタイプ」を指定する記述。(省略可能。)
    記述されるデータの MIME タイプを指定。(既定値は「text/plain;charset=US-ASCII」。)
  3. 「データの書式」を指定する記述。(省略可能。)
    記述されるデータの書式が「Percent-Encoding」なのか「base64」なのかを、セミコロン「;」を最初に付けて記述。(既定値は「Percent-Encoding」なので、「base64」の場合だけ記述すれば良い。)
  4. 「データ」を記述。(必須。)
    データそのものとなる文字列を記述する。カンマ「,」を最初に付けて任意のデータを記述。

 

[ Data URL Schemeの記述例 ]

<a>タグのhref属性に「Data URL Scheme」を設定する例。

  1. URLスキームである「data:」を記述。
  2. コンテンツタイプを記述。(ここでは「text/html」。)
  3. セミコロン「;」のあとに文字セットを記述。(ここでは「charset=UTF-8」。)
  4. 書式は省略。(ここでは「Percent-Encoding」したデータを記述するので。)
  5. カンマ「,」のあとにデータを記述。(ここではhtmlの内容「<!DOCTYPE html><html lang=”ja”><head><meta charset=”UTF-8″></head><body><p>テストテキスト。</p></body></html>」を「Percent-Encoding」した文字列を記述。)

※ JavaScriptで文字列を「Percent-Encoding」するには、「encodeURIComponent()」メソッドを使用する。

※ HTML5の「download」属性を使用すると指定のファイル名でダウンロードすることができる。(IEは非対応。)

※ ブラウザは、記述されているデータURLを解析し、MIMEタイプと書式を元にしてデータの文字列をバイナリーデータに複合する。

<a href="data:text/html;charset=UTF-8,%3C!DOCTYPE%20html%3E%3Chtml%20lang%3D%22ja%22%3E%3Chead%3E%3Cmeta%20charset%3D%22UTF-8%22%3E%3C%2Fhead%3E%3Cbody%3E%3Cp%3E%E3%83%86%E3%82%B9%E3%83%88%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%80%82%3C%2Fp%3E%3C%2Fbody%3E%3C%2Fhtml%3E" download="test.html">リンクテスト</a>

 

 

Fileオブジェクト

(1) Fileオブジェクト

「File」オブジェクトは「Blob」を継承していて、ファイルシステムに関連した機能が拡張されている。

  • 「File」オブジェクトは、特別な種類の「Blob」オブジェクトで、「Blob」が利用できる場面ではどこでも利用できる。
  • 「File」インターフェイス自体にはメソッドが定義されておらず、「Blob」インターフェイスからメソッドを継承している。

「File」オブジェクトを生成する方法は、下記のどちらか。

  1. File()コンストラクターを使って「File」オブジェクトを新たに生成する方法。(IEは非対応。)
  2. HTMLのinput要素や、ブラウザへのドラッグドロップなど、ブラウザのインターフェイスを使用して、PCなどのローカルファイルを「File」オブジェクトとして取得する方法。

 

(2) File()コンストラクター

File()コンストラクターは、新たなFileオブジェクトを生成して返す。生成されたFileオブジェクトの中身は、引数で与えられた値を連結したもので構成される。(IEはFile()コンストラクターに非対応。)

※ File()コンストラクターについてのMozillaの公式ドキュメント

 

[ Fileオブジェクトを生成する例 ]

File()コンストラクターで、ファイル名が「ag2.txt」で内容が「hello world」というテキストファイルのFileオブジェクトを生成する例。

  1. new演算子を付加し、引数に「データの配列」、「ファイル名」、「コンテンツタイプ」を指定してFile()コンストラクターを呼び出す。(引数で与えられた配列を連結したものでデータの中身が構成される。)
  2. Fileオブジェクトが生成され、指定したデータ内容のバイナリーデータが内部的にメモリに保持される。
let ag2file = new File(['hello', ' ', 'world'], 'ag2.txt', {type: 'text/plain'});

new File([データの配列], ファイル名, オプション) : 引数で指定した内容で新しく作成されたFileオブジェクトを返す。第1引数にファイルの内容となるデータの配列、第2引数にファイル名またはファイルへのパス、第3引数にファイルの種類となるMIMEタイプを指定する。(第1引数は配列である必要がある。)

  • データの配列 : 「バッファーのデータ」(ArrayBuffer)、「文字列」(USVString)、「Blobオブジェクト」(Blob)のいずれか(または組み合わせ)を配列で指定。
  • ファイル名 : USVStringで、「ファイル名」または「ファイルへのパス」を指定。
  • オプション : 任意で以下の2つのオプションが指定できる。省略可。
    type : 設定したデータの「MIMEタイプ」(DOMString)を指定。既定値は空文字「”」。
    lastModified : ファイルが最後に更新された時刻を表す数値(ミリ秒)を指定。UNIXタイムスタンプ。既定値は「Date.now()」。

 

(3) HTMLのinput要素で取得

HTMLのinput要素でローカルファイルを選択して、任意のファイルを「File」オブジェクトとして取得する方法。

[ 1. HTMLのマークアップ ]

HTMLのinput要素で任意のローカルファイルを選択。

  1. 「type」属性に「file」を指定してローカルファイルを選択できるようにする。
  2. 選択できるファイルの種類を制限する場合は、「accept」属性を設定。(下記では画像ファイルのみ許可。)
  3. 一度に複数のファイルを選択できるようにする場合は、「multiple」属性を付与。
<input id="ag2input" type="file" accept="image/*" multiple>

[ 2. JavaScriptで取得 ]

(ユーザーがファイル選択後に)input要素が保持する「選択されたファイルのFilelistオブジェクト」から個々のファイルをFileオブジェクトとして取得。

  1. 「change」イベントを捕捉。(input要素でファイルが選択されたら発火。)
  2. input要素で選択されたファイルのFilelistオブジェクトを取得。
  3. Filelistオブジェクトから個々のFileオブジェクトを取得。
//input要素を取得
const ag2input = document.getElementById('ag2input');
ag2input.addEventListener('change', function(){
  //Filelistオブジェクトを取得
  let ag2files = this.files,
      ag2fileNum = this.files.length;
  for(let i = 0; i < ag2fileNum; i++){
    //Fileオブジェクトを取得
    let thisFile = ag2files[i];
    console.log(thisFile.name);//ファイル名
    console.log(thisFile.lastModified);//UNIXタイムスタンプをミリ秒 (IE非対応)
    console.log(thisFile.size);//ファイルサイズ
    console.log(thisFile.type);//MIMEタイプ
  }
});

 

 

FileReaderオブジェクト

(1) FileReaderオブジェクト

「FileReader」オブジェクトは、「Blob」オブジェクトや「File」オブジェクトからデータを読み込むことのみを目的としたオブジェクト。

「FileReader」オブジェクトは、メソッドを使用してBlobや任意のローカルファイル(Fileオブジェクト)のデータを指定のフォーマットで読み込むことができる。

※ FileReaderについてのMozillaの公式ドキュメント

 

(2) FileReader()コンストラクター

「FileReader」オブジェクトを生成するには、FileReader()コンストラクターを使う。

  1. new演算子を付加し、引数無しでFileReader()コンストラクターを呼び出す。
  2. FileReaderオブジェクトが生成される。
let ag2reader = new FileReader();

 

(3) FileReaderの主なメソッド

FileReaderオブジェクトが持つメソッドの引数にBlobオブジェクト(またはFileオブジェクト)を指定して、Blobの内容を読み込む。

[ 主なメソッド ]

  • readAsText() : データを文字列で読み込む。
  • readAsArrayBuffer() : データをArrayBufferで読み込む。
  • readAsDataURL() : データをbase64エンコードのData URLで読み込む。
  • readAsBinaryString() : 生のバイナリーデータを文字列で読み込む。(後方互換のための実装。readAsArrayBufferの使用が推奨されている。)

※ 動的なデータの読み込み処理が発生するので、読み込んだデータを使用する場合は読み込み完了を捕捉してから実行する必要がある。

※ 読み込みのメソッドを実行すると、内部処理の進捗に合わせて「progress」や「load」などのFileReaderのイベントが発火する。

※ 読み込み操作を中止したい場合は、「abort()」メソッドを使う。

//BlobオブジェクトをData URLにして読み込む場合
ag2reader.readAsDataURL(ag2blob);
//データの読み込みが完了したら実行
ag2reader.addEventListener('load', function(){
 //データ読み込みに成功した場合
 console.log(ag2reader.result);
});
ag2reader.addEventListener('error', function(){
 //データ読み込みに失敗した場合
 console.log(ag2reader.error);
});

 

 

この記事のURL

https://memo.ag2works.tokyo/post-4332/

Copyコピー
この記事のタイトル

Blobの基礎知識。 | memo メモ [AG2WORKS]

Copyコピー
この記事のリンクタグ

<a href="https://memo.ag2works.tokyo/post-4332/" target="_blank" rel="noopener">Blobの基礎知識。 | memo メモ [AG2WORKS]</a>

Copyコピー
※ フィールドをクリックでコピーするテキストの編集ができます。

この記事へのコメント

コメントの書き込みはまだありません。

  • コメント内のタグはエスケープ処理され、文字列として出力されます。
  • セキュリティーのため、投稿者のIPアドレスは取得されます。
  • 管理者が内容を不適切と判断したコメントは削除されます。
  • このフォームにはスパム対策として、Googleの提供するreCAPTCHAシステムが導入されています。
    (Google Privacy Policy and Terms of Service.)