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

Electronで[desktopCapturer](https://github.com/electron/electron/blob/master/docs/api/desktop-capturer.md)をする際に、file,blob,dataUriを扱ったので、忘れないうちにメモしておきます。

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

そのプロパティに`NativeImage`があって、[NativeImageのインスタンスのメソッド](https://github.com/electron/electron/blob/master/docs/api/native-image.md#class-nativeimage)の中に`toPNG`というものがあり、直接ローカルに保存するのはnode.jsの`fs.writeFile`で実現できたのですが、Rails5のAPIを叩いてファイルをPOSTする方法がわからずにいました。

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

結論は、[FormData](https://developer.mozilla.org/ja/docs/Web/API/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 について](https://hakuhin.jp/js/data_uri_scheme.html)をご覧ください。

### 補足：スキームとは
`{スキーム名}:{スキームの中身？}`で表され、スキーム名には「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 クラスについて](https://hakuhin.jp/js/file.html)をご覧ください。

## Bufferをざっくり知る

node.jsでは[Bufferクラス](https://nodejs.org/api/buffer.html)、JavaScriptではMDNに[ArrayBuffer](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer)のドキュメントがあります。

MDNではこのように説明されています。
> ArrayBuffer は、一般的な固定長のバイナリデータのバッファを示すために使われるデータタイプです。

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

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

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

## Data URIをBlob/Fileにする

```javascript
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について](https://hakuhin.jp/js/base64.html)
[Data URIからBlob(File)を作成する方法](https://lab.syncer.jp/Web/JavaScript/Snippet/26/)
[Convert Data URI to File then append to FormData
](https://stackoverflow.com/questions/4998908/convert-data-uri-to-file-then-append-to-formdata)

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