LoginSignup
19
21

More than 5 years have passed since last update.

Angular環境でWebCam画像をS3に直接アップロードする(個人的メモ)

Last updated at Posted at 2014-07-25

目的

・Angular環境でWebカメラで撮影したjpg画像ファイルをS3に直接アップロードする実装にハマったのでメモしておく。
・webカメラから画像を出力するところは簡単なので省略。(ブラウザの種類によって動かなかったりしますが。)
・S3についてはPre-signed URLをサーバ側で取得しましたが、そこもハマらなかったので省略。
・問題になったのは、画像ファイルをアップロードする部分なので、その界隈のみをクローズアップする。

ハマったところ

・まず、html5 canvasのtoDataURLで画像出力するとBase64形式になり、かつデータの前にフォーマットを示す文字列がくっついてしまう。このため、Base64形式のデータをいったんBLOBに出力する必要がある。この辺まではググればいくつか情報があるのでなんとかなる。(後ほどソースつけます。)
・BLOBデータをアップロードする部分で、Ajax呼び出しというかXMLHttpRequestで実装しようとして、FormDataとか準備してやったところ、S3にアップロードしたファイルがMIME形式のまま(いわゆるBoundaryの文字列とかそのままくっついたままのこと)保存されてしまい、どうにもならなかった。
・Webで調べてもXHRでアップロード文字列を組み立ててS3アップロードしている事例は結構見つかったが、どうにもうまくいかず。結局、XHRではなくAngularの通常の$httpでBLOBをアップロードしたところうまくいった。なんだ、それだけのことか、、という感じですが、かれこれ3日ほど悩みました。

実装サンプル

・Controller部分だけだが、以下の通り。


    var contentType = 'image/jpeg';
    //var contentType = 'image/png';

    //DataURL(Base64形式)をBlobに変換
    function dataURItoBlob(dataURI) {
      //DataURLのデータ部分をBase64からデコード
      var binary = atob(dataURI.split(',')[1]);
      var array = [];
      // Arrayに 1 バイトずつ値を埋める
      for(var i = 0; i < binary.length; i++) {
        array.push(binary.charCodeAt(i));
      }
      //BLOB形式に変換
      return new Blob([new Uint8Array(array)], {type: contentType});
    }
    //ファイルアップロード
    function uploadPicture(callback) {
      console.log('uploadPicture START!!');

      //画像情報作成(BLOB形式)
      var canvas = document.getElementById('myCanvas');
      var dataURL = canvas.toDataURL(contentType);
      var blob = dataURItoBlob(dataURL);

      //アップロード用のURL取得
      $http({
        method: 'GET',
        url: '/api/xxxx/' 
      })
      .success(function(data) {
        var uploadURL = data.url;

        //画像アップロード
        $http({
          method: 'PUT',
          url: uploadURL,
          headers: {
            'Content-Type': contentType,
          },
          data: blob,
        })
        .success(function(data) {
          console.log('アップロード完了 data:',data);
          callback();
        })

        .error(function(data, status) {
          console.log('アップロード失敗 status:',status);
          console.log('アップロード失敗 data:',data);
        });
      })
      .error(function(data, status) {
        console.log('get upload url error status:',status);
        console.log('get upload url error data:',data);
      });
    }

19
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
21