質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.85%

[iOSのみうまく動かない] javascript input:file から画像リサイズ後にajaxにてS3へ直接アップロード、Deferedを返す

受付中

回答 0

投稿

  • 評価
  • クリップ 1
  • VIEW 1,298

dk1987

score 30

iOSのみ画像アップロード系でうまく動かず、知見をお借りしたいです... 具体的には、下記のような流れを処理しているのですが、iOSの時のみ、AjaxのDeferredで、rejectが返ってきてしまいます。。。なのですが、resolveも同時に返ってきているようでして、修正方法がわからず、お力をお借りしたいです。

処理の流れを記載します。
・getS3PolicyAndUploadImageToS3 引数は、input:fileから取り出したファイルオブジェクトを与える
・Deferedオブジェクトを返すようにしておく - return defer.promise();
・画像を1000px * 1000px以内にリサイズ
・S3用のシグネチャをtabi-muse.comサーバへ取得しに行き
・アップロードはシグネチャを利用し、S3へダイレクトアップロード
・S3のアップロードまで成功すれば、defer.resolve にて、画像のURLフルパスを返す

ここで、iOSの場合resolveと、rejectが両方とも返ってきているような動きになってしまっているのです。

具体的にはrejectであればエラーとして処理しアラートを出す処理にしているのですが、iOSではアラートが出るにもかかわらず、URLフルパスも正しく返ってきておりまして、S3へ保存したURLをその後DBへ保存する処理まで成功しています。

長文で申し訳ありません.... 何かご存知でしたら、ご教授頂けますと幸いです。

iOSのFileObject系の取扱が怪しいのではと思っているのですが、具体的原因が不明で解決方法が思いつかずな状況です。

Javascript側で無茶しすぎでしょうか....

UTIL.getS3PolicyAndUploadImageToS3 = function(file){
    // 20160504 - resize image to max 1000 * 1000 - start
    var fileRdr = new FileReader();
    var defer = $.Deferred();

    fileRdr.onload = function() {
      var image = new Image();
      image.src = fileRdr.result;
      image.onload = function (imageEvent) {
        // Resize the image
        var canvas = document.createElement('canvas'),
          max_size = 1000,
          width = image.width,
          height = image.height;
        if (width > height) {
          if (width > max_size) {
            height *= max_size / width;
            width = max_size;
          }
        } else {
          if (height > max_size) {
            width *= max_size / height;
            height = max_size;
          }
        }
        canvas.width = width;
        canvas.height = height;
        canvas.getContext('2d').drawImage(image, 0, 0, width, height);
        var dataURL = canvas.toDataURL('image/jpeg');
        var blob = UTIL.dataURItoBlob(dataURL);
        //var newFile = new File([blob], file.name);

        //サーバサイドとの通信によるtoken取得と、S3へのアップロードを担う
        //@param fileObject,
        var data = {ctype:blob.type, clength:blob.size};
        // まずはサーバからpolicyとsignatureを取得.
        $.ajax({
          url: '/ApiImages/getS3Policy',
          type: 'GET',
          dataType: 'json',
          data: data,
          cache : false,
          timeout: 500000
        }).then(function(data){
          // サーバが返した情報をそのまま使ってFormDataを作る.
          var name, fd = new FormData();
          for (name in data.form) if (data.form.hasOwnProperty(name)) {
            fd.append(name, data.form[name]);
          }
          fd.append('file', blob); // ファイル添付.

          // 送信
          var xhr = new XMLHttpRequest();
          xhr.open('POST', data.url, true);
          xhr.onreadystatechange = function (oEvent) {
            if (xhr.readyState == 4) {
              if (xhr.status == 200) {
                console.log(xhr.responseText);
                defer.resolve(data.url + data.form.key); //画像のURLフルパスを返す
              } else {
                defer.reject("画像アップロードに失敗しました。");
                console.log("Error", xhr);
              }
            }
          };
          xhr.upload.addEventListener('progress',function(e){
            console.log(parseInt(e.loaded/e.total*100));
            UTIL.progressbarOverlay.progress(parseInt(e.loaded/e.total*100));
          }, false);
          xhr.send(fd);
        }, function(jqXHR, textStatus, errorThrown){
          defer.reject("画像アップロードに失敗しました。");
        });
      }
    };

    fileRdr.readAsDataURL(file);
    return defer.promise();
    // 20160504 - resize image to max 1000 * 1000 - end
  };
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正の依頼

  • Lhankor_Mhy

    2016/05/28 11:28

    『resolveと、rejectが両方とも返ってきている』とありますが、UTIL.getS3PolicyAndUploadImageToS3()の.done()と.fail()の両方が動作してるということでしょうか。その際の.state()の値はどうなっていますか? UTIL.getS3PolicyAndUploadImageToS3()が二重サブミットのような理由で複数回呼ばれることはないでしょうか?

    キャンセル

まだ回答がついていません

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.85%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる