ニフクラmBaaSお役立ちブログ

スマホアプリ開発にニフクラmBaaS。アプリ開発に役立つ情報をおとどけ!

Monacaで画像アップロード/ダウンロードを行うには

https://cdn-ak.f.st-hatena.com/images/fotolife/f/fjct/20171019/20171019094046.png

スマートフォンアプリとして写真を扱いたいと思う人は多いかと思います。JavaScript SDK v2.1.1よりWebブラウザでもファイルストアへのアップロードが行えるようになり、Monacaアプリで写真のアップロード/ダウンロードができるようになりました。

そこで今回はサンプルコードを使って実装方法を紹介します。

基本形

まずはNCMBの読み込みと、アプリ起動時のイベントを作成します。

var application_key = "YOUR_APPLICATION_KEY";
var client_key = "YOUR_CLIENT_KEY";

var ncmb = new NCMB(application_key, client_key);

function onDiviceReady() {

}

document.addEventListener("deviceready", onDiviceReady, false);

後は onDiviceReady 内に処理を書いていきます。

ファイル選択時の処理について

まずファイルを選択したらサムネイルを表示するようにします。そのために FileReaderクラスを用意します。

var reader = new FileReader();
reader.onload = function(e) {
  var dataUrl = reader.result;
  document.getElementById("image").src = dataUrl;
}

FileReaderクラスは読み込んだファイルを img#image に表示します。

ではファイルを選択した際の処理を書きます。input#photo で写真を選択したらchangeイベントが実行されますのでファイル名を残しておきます。

// ファイルを選択したら実行
var photo = document.getElementById("photo");
photo.addEventListener('change', function(e) {
  e.preventDefault();
  var file = e.target.files[0];
  document.getElementById("filename").value = file.name
  reader.readAsDataURL(file);
}, false);

ここまでできるとファイルを選択したら画像が表示されるようになります。

ファイルをアップロードする

続いてファイルのアップロードですが、imgタグの中に出力したデータはdataURIになるので、Blobに変換する必要があります。その関数は以下の通りです。

// dataURIをBlobに変換
function dataURItoBlob(dataURI) {
  var byteString;
  if (dataURI.split(',')[0].indexOf('base64') >= 0)
    byteString = atob(dataURI.split(',')[1]);
  else
    byteString = unescape(dataURI.split(',')[1]);
  var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
  var ia = new Uint8Array(byteString.length);
  for (var i = 0; i < byteString.length; i++) {
    ia[i] = byteString.charCodeAt(i);
  }
  return new Blob([ia], {type:mimeString});
}

後はアップロードボタンのクリックイベントに合わせて ncmb.File.upload を実行します。

// ファイルアップロード
var submit = document.getElementById("submit");
submit.addEventListener("click", function(e) {
  e.preventDefault();
  // ファイル名、ファイルデータを取得
  var fileName = document.getElementById("filename").value;
  var fileData = dataURItoBlob(document.getElementById("image").src);
  
  // アップロード
  ncmb.File.upload(fileName, fileData)
    .then(function(res) {
      console.log(res);
    })
    .catch(function(err) {
      console.error(err);
    })
}, false)

ファイルのダウンロード

ファイルをダウンロードする際にはダウンロード対象のファイル名が必要です。また、今回はバイナリデータをダウンロードするので、ncmb.File.download の2つ目の引数を blob と指定してください。

// ファイルダウンロード
var view = document.getElementById("view");
view.addEventListener("click", function(e) {
  e.preventDefault();
  // ファイル名を取得
  var fileName = document.getElementById("filename").value;
  
  // ダウンロード(バイナリなのでblobを指定)
  ncmb.File.download(fileName, "blob")
    .then(function(blob) {
      // ファイルリーダーにデータを渡す
      reader.readAsDataURL(blob);
    })
    .catch(function(err) {
      console.error(err);
    })
}, false);

これでファイル名を指定して画像をダウンロード、img#image に画像を表示できます。


全体のコードは次のようになります。

var application_key = "YOUR_APPLICATION_KEY";
var client_key = "YOUR_CLIENT_KEY";

var ncmb = new NCMB(application_key, client_key);

function onDiviceReady() {
  
  var reader = new FileReader();
  reader.onload = function(e) {
    var dataUrl = reader.result;
    document.getElementById("image").src = dataUrl;
  }
  
  // ファイルを選択したら実行
  var photo = document.getElementById("photo");
  photo.addEventListener('change', function(e) {
    e.preventDefault();
    var file = e.target.files[0];
    document.getElementById("filename").value = file.name
    reader.readAsDataURL(file);
  }, false);
  
  // ファイルアップロード
  var submit = document.getElementById("submit");
  submit.addEventListener("click", function(e) {
    e.preventDefault();
    // ファイル名、ファイルデータを取得
    var fileName = document.getElementById("filename").value;
    var fileData = dataURItoBlob(document.getElementById("image").src);
    
    // アップロード
    ncmb.File.upload(fileName, fileData)
      .then(function(res) {
        console.log(res);
      })
      .catch(function(err) {
        console.error(err);
      })
  }, false)
  
  // ファイルダウンロード
  var view = document.getElementById("view");
  view.addEventListener("click", function(e) {
    e.preventDefault();
    // ファイル名を取得
    var fileName = document.getElementById("filename").value;
    
    // ダウンロード(バイナリなのでblobを指定)
    ncmb.File.download(fileName, "blob")
      .then(function(blob) {
        // ファイルリーダーにデータを渡す
        reader.readAsDataURL(blob);
      })
      .catch(function(err) {
        console.error(err);
      })
  }, false);
}

// dataURIをBlobに変換
function dataURItoBlob(dataURI) {
  var byteString;
  if (dataURI.split(',')[0].indexOf('base64') >= 0)
    byteString = atob(dataURI.split(',')[1]);
  else
    byteString = unescape(dataURI.split(',')[1]);
  var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
  var ia = new Uint8Array(byteString.length);
  for (var i = 0; i < byteString.length; i++) {
    ia[i] = byteString.charCodeAt(i);
  }
  return new Blob([ia], {type:mimeString});
}

document.addEventListener("deviceready", onDiviceReady, false);

さいごに

今回のコードは moongift/MonacaFileUploadDemo にMonacaプロジェクトとしてアップロードしてあります。写真に限らずバイナリデータをアップロード、ダウンロードする際の参考にしてください。

ドキュメント : 開発者向けドキュメント | ニフティクラウド mobile backend