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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Amazon S3

Amazon S3 (Simple Storage Service)とはアマゾン・ウェブ・サービスが提供するオンラインストレージサービスです。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

0回答

717閲覧

【スマホ対応】Javascriptからs3に画像をアップすると、ファイルの中身が空になってしまう問題を解決したい

tacro

総合スコア23

Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Amazon S3

Amazon S3 (Simple Storage Service)とはアマゾン・ウェブ・サービスが提供するオンラインストレージサービスです。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

0クリップ

投稿2018/04/02 17:29

編集2022/01/12 10:55

前提・実現したいこと

Rails5で開発をしています。
jQuery file uploadを使用して、ユーザーが画像をトリミング後、クライアント側からS3へ直接画像をアップロードする機能を実装しています。
PC(MacBook Pro)のchromeからは問題なくアップロードができるのですが、PCとiPhoneのsafari、およびiPhoneのchromeからアップすると、ファイルの中身が空っぽになってしまう問題が発生しています。

発生している問題・エラーメッセージ

トリミングをしない通常のアップロードはブラウザに関係なく行えるのですが、トリミング後の画像をキャンバスで取得し、blobファイルに変換してアップしようとすると、ブラウザによってはアップロードがうまくいきません。
s3へのファイルのアップロード自体は問題なくできている(指定したディレクトリに、指定した名前でファイルが作成されている)のですが、サイズが0Byteになってしまっています。
一通り調べたのですが、同じような問題を見つけることができず、原因に見当がつきません。
blobファイルの作成がうまくいっていないのでしょうか?
アドバイスをよろしくお願いいたします。

該当のソースコード

Direct to S3 Image Uploads in Rails
を参考に、Javascriptを以下のように書いています。

javascript

1$(function() { 2 $('.directUpload').find("input:file").each(function(i, elem) { 3 var fileInput = $(elem); 4 var form = $(fileInput.parents('form:first')); 5 var submitButton = form.find('input[type="submit"]'); 6 var progressBar = $("<div class='bar'></div>"); 7 var barContainer = $("<div class='progress'></div>").append(progressBar); 8 fileInput.after(barContainer); 9 fileInput.fileupload({ 10 fileInput: fileInput, 11 url: form.data('url'), 12 type: 'POST', 13 autoUpload: false, 14 formData: form.data('form-data'), 15 paramName: 'file', // S3 does not like nested name fields i.e. name="user[avatar_url]" 16 dataType: 'XML', // S3 returns XML if success_action_status is set to 201 17 replaceFileInput: false, 18 acceptFileTypes: /(.|/)(gif|jpe?g|png)$/i, 19 // singleFileUploads: false, 20 maxNumberOfFiles: 1, 21 sequentialUploads: true, 22 limitMultiFileUploads:1, 23 limitConcurrentUploads: 1, 24 25 add: function(e, data){ 26 if (data.files && data.files[0]) { 27 var reader = new FileReader(); 28 reader.onload = function(e) { 29 $('.preview').empty(); 30 $('.preview').append($('<img>').attr({// insert preview image 31 src: e.target.result, 32 id: "crop_img", 33 title: data.files[0].name 34 })); 35 $('#crop_img').cropper() // initialize cropper on preview image 36 }; 37 reader.readAsDataURL(data.files[0]); 38 }; 39 40 submitButton.on('click', function(){ 41 $('form').submit(function(){ 42 return false; 43 }); 44 // crop のデータを取得 45 $('#crop_img').cropper('getCroppedCanvas').toBlob(function (blob){ 46 data.files[0] = new File([blob], data.files[0].name); 47 data.originalFiles[0] = data.files[0]; 48 data.submit(); 49 }) 50 }); 51 }, 52 53 progressall: function (e, data) { 54 var progress = parseInt(data.loaded / data.total * 100, 10); 55 progressBar.css('width', progress + '%') 56 }, 57 58 start: function (e) { 59 submitButton.prop('disabled', true); 60 61 progressBar. 62 css('background', 'black'). 63 css('display', 'block'). 64 css('width', '0%'). 65 text("Loading..."); 66 }, 67 68 done: function(e, data) { 69 submitButton.prop('disabled', false); 70 progressBar.text("Uploading done"); 71 72 // extract key and generate URL from response 73 var key = $(data.jqXHR.responseXML).find("Key").text(); 74 var url = '//' + form.data('host') + '/' + key; 75 76 // create hidden field 77 var input = $("<input />", { type:'hidden', name: fileInput.attr('name'), value: url }) 78 form.append(input); 79 80 //delete submit event which is false 81 $('form').off('submit'); 82 //and submit again 83 $('.directUpload').submit(); 84 }, 85 86 fail: function(e, data) { 87 submitButton.prop('disabled', false); 88 89 progressBar. 90 css("background", "red"). 91 text("Upload Failed!"); 92 } 93 }); 94 }); 95}); 96

試してみたこと 1

JavaScript-Canvas-to-Blobをviewに付け足してみましたが、変わりありませんでした。
テストサイトにアクセスして、このpolyfill自体がiOSのsafari上で動くことは確認できました

試してみたこと 2

toBlob() メソッドを使う代わりに、以下のコードで試してみましたが、変わりありませんでした…

javascript

1 // crop のデータを取得 2 // $('#crop_img').cropper('getCroppedCanvas').toBlob(function (blob){ 3 // data.files[0] = new File([blob], data.files[0].name); 4 // data.originalFiles[0] = data.files[0]; 5 // data.submit(); 6 // }) 7 //以上のコードを以下に置換 8 var canvas = $('#crop_img').cropper('getCroppedCanvas'); 9 var canvas_data = canvas.toDataURL(); 10 var blobData = dataURItoBlob(canvas_data); 11 function dataURItoBlob(dataURI) { 12 var binary = atob(dataURI.split(',')[1]); 13 var array = []; 14 for(var i = 0; i < binary.length; i++) { 15 array.push(binary.charCodeAt(i)); 16 } 17 return new Blob([new Uint8Array(array)], {type: 'image/jpeg'}); 18 } 19 data.files[0] = new File([blobData], data.files[0].name); 20 data.originalFiles[0] = data.files[0]; 21 data.submit();

試してみたこと 3

safariのコンソールでdata.submit()直前のdata,data.files[0],data.filesの中身を確認してみたところ、それぞれ正しく中身が確認されました。
fileuploadライブラリのsubmit()メソッドの問題かもしれません。

javascript

1$('#crop_img').cropper('getCroppedCanvas').toBlob(function (blob){ 2 data.files[0] = new File([blob], data.files[0].name); 3 data.originalFiles[0] = data.files[0]; 4 console.log(data.files[0]); 5 console.log(data); 6 console.log(data.files); 7 // at this point the data is correct on both browsers 8 data.submit(); 9 // but submitted file is empty 10 })

補足情報(FW/ツールのバージョンなど)

Ruby on Rails 5
サーバー:heroku hobby
試した機種とブラウザ:
[MacBook Pro]
Chrome:問題なく成功
Safari:アップロードはされているが、ファイルの中身が空

[iPhone 7]
Chrome:アップロードはされているが、ファイルの中身が空
Safariアップロードはされているが、ファイルの中身が空

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

h_daido

2018/04/16 11:20

問題の切り分けが必要そうですすね。iphone7をMacBookとつなげて、safariのwebインスペクタを起動できますか?networkタブでs3に対するリクエストとレスポンスが見れるはずなので、そこの値を確認してみると良いかと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問