DataURI, Blob, File, (Array)Bufferをざっくり知る。


ElectronでdesktopCapturerをする際に、file,blob,dataUriを扱ったので、忘れないうちにメモしておきます。

desktopCapturer.getSources(options, callback) をすると、callbackに DesktopCapturerSource objectsなるものが帰ってきて、

そのプロパティにNativeImageがあって、NativeImageのインスタンスのメソッドの中にtoPNGというものがあり、直接ローカルに保存するのはnode.jsのfs.writeFileで実現できたのですが、Rails5のAPIを叩いてファイルをPOSTする方法がわからずにいました。

HTMLのフォームを作成してsubmitするのはできたのですが、フォームを使わずにPOSTしたかったのです。

結論は、FormDataにfileオブジェクトをappendして、POSTすればよかったのでした。

これをするために、toDataURLメソッドからfileオブジェクトを生成しました。以下、その内容です。

DataURLをざっくり知る

dataURIや、dataURIスキーム、dataスキームのURL、などと言われるみたいです。dataスキームが先頭についているURLということでしょう。

DataURLは、<img src='ココと置換可能'>です。

DataURLのサンプルはこんな感じです。data:image/png;base64,iVBO...(長いので以下略)srcにhttpから始まるURLを指定すると、データの読み込みにhttp通信が発生して時間がかかりますが、dataURIだと通信がいらないため、処理が早く済むのだとか。

詳しく知りたい場合はData URI Scheme についてをご覧ください。

補足:スキームとは

{スキーム名}:{スキームの中身?}で表され、スキーム名には「file, blob, data, http, ftp」などがあります。

Blobをざっくり知る

クラスです。バッファデータとコンテンツタイプデータを引数にもちます。
new Blob ( [バッファデータ], オプション )するとBlobオブジェクトが返ってきます。ローカルにあるファイルと同じ雰囲気。

Fileをざっくり知る

同じく、クラスです。BlobクラスはFileクラスから派生しています。Blob > File。
new File ( [バッファデータ], ファイル名, オプション )するとFileオブジェクトが返ってきます。

desktopCapturerで取得する画像ファイルは、名前をつけてAPIにPOSTして、carrierwave経由でフォルダに保存したかったので、Fileクラスでファイル名を指定できるのは助かりました。

BlobとFileを詳しく知りたい場合はBlob と File クラスについてをご覧ください。

Bufferをざっくり知る

node.jsではBufferクラス、JavaScriptではMDNにArrayBufferのドキュメントがあります。

MDNではこのように説明されています。

ArrayBuffer は、一般的な固定長のバイナリデータのバッファを示すために使われるデータタイプです。

補足:バッファとは

引用した説明文が理解不能だったので単語を調べてみると、バッファとは、データを一時的に保持するための場所のようです。

補足:バイナリデータとは

バイナリ形式のデータのことで、コンピュータが理解できるデータのようです。この文章みたいに、人間が読んでわかるデータは、テキストデータと言われるそうです。

補足:データタイプとは

データ型のようです。文字列型とか整数型とかブーリアン型とか。その仲間には、バイナリ型というバイナリデータを扱うデータタイプもあるようです。

Data URIをBlob/Fileにする

function dataURIConverter(dataURI) {
    // base64/URLEncodedデータを文字列としてバイナリデータに変換する
    var byteString = atob(dataURI.split(',')[1]);

    // mimetypeを抜き出す
    var mimeType = dataURI.split(',')[0].split(':')[1].split(';')[0];

    // バイナリデータを扱えるように、typed arrayに書き換えていく
    var buffer = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) {
        buffer[i] = byteString.charCodeAt(i);// charCodeAtで配列に
    }

    // 第一引数は配列で渡し、Fileオブジェクトを返す。
    return new File([buffer], 'ファイル名', { type:mimeType } );
}

desktopCapturer.getSources(options, function(error, sources) {
    sources.forEach(function(source) {
        var val = dataURItoFile(source.thumbnail.toDataURL());
        var formData = new FormData();
        formData.append('key', val);

        // ajaxなどでformDataをPOSTしてAPIを叩く。(詳細は割愛)
    }
}

その他参考にさせていただいたページ

base64について
Data URIからBlob(File)を作成する方法
Convert Data URI to File then append to FormData

詳しく知るには、まだまだ調べることがたくさんありそうです。