Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

More than 3 years have 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との併用によって、できることが増えると覚えておくと良いでしょう。

coboco
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away