[iOSのみうまく動かない] javascript input:file から画像リサイズ後にajaxにてS3へ直接アップロード、Deferedを返す
受付中
回答 0
投稿
- 評価
- クリップ 1
- VIEW 1,722
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ページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
まだ回答がついていません
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.35%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正の依頼
Lhankor_Mhy
2016/05/28 11:28
『resolveと、rejectが両方とも返ってきている』とありますが、UTIL.getS3PolicyAndUploadImageToS3()の.done()と.fail()の両方が動作してるということでしょうか。その際の.state()の値はどうなっていますか? UTIL.getS3PolicyAndUploadImageToS3()が二重サブミットのような理由で複数回呼ばれることはないでしょうか?