Edited at
MonacaDay 8

Monaca(Cordova)のCameraプラグインで取得した写真をBlob形式に変換する方法

More than 1 year has passed since last update.

写真を外部ストレージにアップロードする場合などに、Blob形式の写真データが必要になることがあるかと思います。しかしCameraプラグインの写真の取得形式はURIまたはbase64になるため、そのままではBlobデータとして扱えません。

JavaScriptでBlobデータを作るにはnew Blob()を使いますが、このコンストラクタ引数にはArrayBuffer(など)の形式のデータを指定しなければなりません。そのため、写真のURIから最終的にBlobへ変換するには、少々面倒ですが以下の手順を経由する必要があります。


  1. Cameraプラグインで写真のURIを取得

  2. URIからFileEntryに変換

  3. FileEntryからFileオブジェクトを取得し、ArrayBufferに変換

  4. ArrayBufferからBlobに変換

変換処理には、HTML5のFile APIを利用します。

それでは各手順を詳しく解説していきます。


1. Cameraプラグインで写真のURIを取得

まずは写真をURI形式で取得します。

// 写真を読み込み

navigator.camera.getPicture(onSuccess, onError, {
sourceType : Camera.PictureSourceType.PHOTOLIBRARY,
destinationType: Camera.DestinationType.FILE_URI
});

// 写真のURIが取得される
function onSuccess(imageURI) {
// URIからFileEntryに変換
URItoFileEntry(imageURI);
}

// エラー時の処理
function onError(error) {
console.log(error);
}


2. URIからFileEntryに変換

FileEntryは、ローカルのファイルシステム内のファイルを表すインターフェースです。

window.resolveLocalFileSystemURL() によって、FileEntryを取得することができます。

この処理は非同期的に実行され、処理が完了すると第二引数に指定したコールバック関数にFileEntryが渡されます。

// URIからFileEntryに変換する

function URItoFileEntry(imageURI) {
window.resolveLocalFileSystemURL(imageURI, fileEntryToArrayBuffer, onError);
}


3. FileEntryからFileオブジェクトを取得し、ArrayBufferに変換

FileEntry.file()によって、読み込み可能なファイルを表すFileオブジェクトを取得します。

そしてファイルの読み込み機能を提供するFileReaderオブジェクトを生成し、FileReader.readAsArrayBuffer()によって、FileオブジェクトをArrayBuffer形式に変換します。このメソッドは非同期で実行され、読み込みが完了するとFileReader.onloadendイベントが発火します。

// FileEntryからFileオブジェクトを取得し、さらにArrayBufferに変換する

function fileEntryToArrayBuffer(fileEntry) {
// Fileオブジェクトを取得
fileEntry.file((file) => {
// FileReaderを生成
let reader = new FileReader();
// ArrayBuffer形式への変換完了時の処理
reader.onloadend = ArrayBufferToBlob;
// ArrayBuffer形式に変換
reader.readAsArrayBuffer(file);
}, onError);
}

// エラー時の処理
function onError(error) {
console.log(error);
}


4. ArrayBufferからBlobに変換

FileReader.onloadendイベントのイベント引数に、ArrayBufferオブジェクトが格納されています。あとはこのArrayBufferオブジェクトを配列形式にしてnew Blob()のコンストラクタに指定するだけです。

// ArrayBufferからBlobに変換する

function ArrayBufferToBlob(event) {
let blob = new Blob([event.target.result])
}


ソースコード全文

// 写真を読み込み

navigator.camera.getPicture(onSuccess, onError, {
sourceType : Camera.PictureSourceType.PHOTOLIBRARY,
destinationType: Camera.DestinationType.FILE_URI
});

// 写真のURIが取得される
function onSuccess(imageURI) {
// URIからFileEntryに変換
URItoFileEntry(imageURI)
}

// URIからFileEntryに変換する
function URItoFileEntry(imageURI) {
window.resolveLocalFileSystemURL(imageURI, fileEntryToArrayBuffer, onError);
}

// FileEntryからFileオブジェクトを取得し、さらにArrayBufferに変換する
function fileEntryToArrayBuffer(fileEntry) {
// Fileオブジェクトを取得
fileEntry.file((file) => {
// FileReaderを生成
let reader = new FileReader();
// ArrayBuffer形式への変換完了時の処理
reader.onloadend = ArrayBufferToBlob;
// ArrayBuffer形式に変換
reader.readAsArrayBuffer(file);
}, onError);
}

// ArrayBufferからBlobに変換する
function ArrayBufferToBlob(event) {
let blob = new Blob([event.target.result])
}

// エラー時の処理
function onError(error) {
console.log(error);
}

このようにFile APIを使うと、バイナリデータを様々な形式に変換することができます。

CameraプラグインはFile APIとの併用によって、できることが増えると覚えておくと良いでしょう。