teratail header banner
teratail header banner
質問するログイン新規登録

質問編集履歴

2

問題部分を追記

2018/04/01 23:43

投稿

tacro
tacro

スコア23

title CHANGED
@@ -1,1 +1,1 @@
1
- [Javascript] Rails5ユーザーがトリミングした画像を、S3に直接アップロードしたい
1
+ [Javascript] Rails5ユーザーがトリミングした画像を、S3に直接アップロードしたい
body CHANGED
@@ -16,7 +16,8 @@
16
16
 
17
17
  ### 発生している問題・エラーメッセージ
18
18
  ⑴元の画像の代わりに、トリミングした画像データをs3にアップロードできません。
19
- を参考に、以下のようにコードを書いたのですが、トリミングされる前の画像データがアップされてしまいます。
19
+ 以下のようにコードを書いたのですが、トリミングされる前の画像データがアップされてしまいます。
20
+ **【追記】2回submitボタンを押すと、2回目の送信ではトリミング後の画像がアップされることがわかりました。**(詳細は後述します。)
20
21
 
21
22
  ⑵また、このコードだと、画像を選択し直した場合、投稿が二つ作成されてしまいます。
22
23
 
@@ -133,7 +134,40 @@
133
134
  どうすれば、トリミング後の画像を、s3にアップすることができるでしょうか?
134
135
  アドバイスをよろしくお願いいたします。
135
136
 
137
+ #試してみたこと
138
+ 以下のようにコードを書き換えて、コンソールでオンクリックアクション時のdata.originalFiles[0]の中身を確認すると、ちゃんとトリミング後の画像になっていました。
139
+ 一度submitボタンを押してアップロードが完了した後、もう一度クリックすると、トリミング後の画像がs3にアップされることがわかりました。
140
+ なぜ1度目のクリックで行かないのでしょうか…
136
141
 
142
+ ```Javascript
143
+ $(function() {
144
+ $('.directUpload').find("input:file").each(function(i, elem) {
145
+ ...
146
+ submitButton.on('click', function(){
147
+ // crop のデータを取得
148
+ $('#crop_img').cropper('getCroppedCanvas').toBlob(function (blob){
149
+ data.files[0] = new File([blob], data.files[0].name);
150
+ data.originalFiles[0] = data.files[0];
151
+ })
152
+ data.submit();
153
+ });
154
+ },
155
+
156
+ ....
157
+
158
+ done: function(e, data) {
159
+ ...
160
+ //アップロード完了時のフォームの提出をキャンセル
161
+ //$('.directUpload').submit(); //submit a form
162
+ },
163
+ ....
164
+
165
+
166
+ });
167
+ });
168
+
169
+ ```
170
+
137
171
  ### 補足情報(FW/ツールのバージョンなど)
138
172
  Ruby on Rails 5
139
173
  aws-sdk (3.0.1, 2.11.25, 2.11.3)

1

発生している問題点を修正

2018/04/01 23:43

投稿

tacro
tacro

スコア23

title CHANGED
File without changes
body CHANGED
@@ -1,100 +1,111 @@
1
1
  ### 前提・実現したいこと
2
2
 
3
3
  Rails5を使って、ユーザーが画像を選択し、自由にトリミングした上で投稿できる機能を実装中です。
4
- Carrierwaveを用いた通常の実装はできたのですが、サーバーにherokuを使用しているのでアップロードが遅くなってしまうことを懸念し、以下の記事参考に、S3に直接アップロードする方法を取ろうとしています。
4
+ Carrierwaveを用いた通常の実装はできたのですが、サーバーにherokuを使用しているのでアップロードが遅くなってしまうことを懸念し、jQuery file-upload使用してクライアントサイドからS3に直接アップロードする方法を取ろうとしています。
5
- [Direct to S3 Image Uploads in Rails
5
+
6
- ](https://devcenter.heroku.com/articles/direct-to-s3-image-uploads-in-rails)
7
6
  画像をトリミングしない場合は問題なくこの方法で実装できたのですが、トリミングさせる際に、以下の問題が生じました。
8
7
  JSの経験に乏しいので、ご助言いただきたいです…
9
8
 
9
+ 参考記事:
10
+ [Direct to S3 Image Uploads in Rails
11
+ ](https://devcenter.heroku.com/articles/direct-to-s3-image-uploads-in-rails)
12
+ [Direct Upload of Image to S3 after Manual Cropping with Cropper.js](https://stackoverflow.com/questions/37910998/direct-upload-of-image-to-s3-after-manual-cropping-with-cropper-js)
13
+ [jQuery-File-Upload](https://github.com/blueimp/jQuery-File-Upload/wiki/Options#singlefileuploads)
14
+
15
+
16
+
10
17
  ### 発生している問題・エラーメッセージ
11
- ⑴元の画像の代わりに、トリミングした画像データをs3にアップロードできない
18
+ ⑴元の画像の代わりに、トリミングした画像データをs3にアップロードできません。
12
- [Direct Upload of Image to S3 after Manual Cropping with Cropper.js
19
+ を参考に、以下のようにコードを書いたのですが、トリミングされる前の画像データがアップされてしまいます。
13
- Ask Question](https://stackoverflow.com/questions/37910998/direct-upload-of-image-to-s3-after-manual-cropping-with-cropper-js)を参考に、以下のようにコードを書いたのですが、トリミングされる前の画像データがアップされてしまいます。
14
20
 
15
- ⑵また、このコードだと、ボタンてもページが遷移せずpostオブジェクトが作成されません
21
+ ⑵また、このコードだと、画像選択直した場合投稿二つ作成されてしいます
16
22
 
17
23
  ```Javascript
18
24
  $(function() {
19
- $('.directUpload').find("input:file").each(function(i, elem) {
25
+ $('.directUpload').find("input:file").each(function(i, elem) {
20
- var fileInput = $(elem);
26
+ var fileInput = $(elem);
21
- var form = $(fileInput.parents('form:first'));
27
+ var form = $(fileInput.parents('form:first'));
22
- var submitButton = form.find('input[type="submit"]');
28
+ var submitButton = form.find('input[type="submit"]');
23
- var progressBar = $("<div class='bar'></div>");
29
+ var progressBar = $("<div class='bar'></div>");
24
- var barContainer = $("<div class='progress'></div>").append(progressBar);
30
+ var barContainer = $("<div class='progress'></div>").append(progressBar);
25
- fileInput.after(barContainer);
31
+ fileInput.after(barContainer);
26
- fileInput.fileupload({
32
+ fileInput.fileupload({
27
- fileInput: fileInput,
33
+ fileInput: fileInput,
28
- url: form.data('url'),
34
+ url: form.data('url'),
29
- type: 'POST',
35
+ type: 'POST',
30
- autoUpload: true,
36
+ autoUpload: false,
31
- formData: form.data('form-data'),
37
+ formData: form.data('form-data'),
32
- paramName: 'file', // S3 does not like nested name fields i.e. name="user[avatar_url]"
38
+ paramName: 'file', // S3 does not like nested name fields i.e. name="user[avatar_url]"
33
- dataType: 'XML', // S3 returns XML if success_action_status is set to 201
39
+ dataType: 'XML', // S3 returns XML if success_action_status is set to 201
34
- replaceFileInput: false,
40
+ replaceFileInput: true,
41
+ acceptFileTypes: /(.|/)(gif|jpe?g|png)$/i,
35
42
 
36
- add: function(e, data){
43
+ add: function(e, data){
37
- if (data.files && data.files[0]) {
44
+ if (data.files && data.files[0]) {
38
- console.log("called");
45
+ console.log("called");
39
- var reader = new FileReader();
46
+ var reader = new FileReader();
40
- reader.onload = function(e) {
47
+ reader.onload = function(e) {
41
- $('.preview').empty();
48
+ $('.preview').empty();
42
- $('.preview').append($('<img>').attr({// insert preview image
49
+ $('.preview').append($('<img>').attr({// insert preview image
43
- src: e.target.result,
50
+ src: e.target.result,
44
- id: "crop_img",
51
+ id: "crop_img",
45
- title: data.files[0].name
52
+ title: data.files[0].name
46
- }));
53
+ }));
47
- $('#crop_img').cropper() // initialize cropper on preview image
54
+ $('#crop_img').cropper() // initialize cropper on preview image
48
- };
55
+ };
49
- reader.readAsDataURL(data.files[0]);
56
+ reader.readAsDataURL(data.files[0]);
50
- };
57
+ };
51
58
 
52
- $('#_submit').on('click', function(){
59
+ submitButton.on('click', function(){
53
- // crop のデータを取得
60
+ // crop のデータを取得
54
- $('#crop_img').cropper('getCroppedCanvas').toBlob(function (blob){
61
+ $('#crop_img').cropper('getCroppedCanvas').toBlob(function (blob){
55
- var croppedFile = new File([blob], data.files[0].name);
62
+ data.files[0] = new File([blob], data.files[0].name);
56
- data.files[0] = croppedFile;
57
- data.originalFiles[0] = data.files[0];
63
+ data.originalFiles[0] = data.files[0];
58
- })
64
+ })
59
- data.submit();
65
+ data.submit();
60
- });
66
+ });
61
- },
67
+ },
62
68
 
63
- progressall: function (e, data) {
69
+ progressall: function (e, data) {
64
- var progress = parseInt(data.loaded / data.total * 100, 10);
70
+ var progress = parseInt(data.loaded / data.total * 100, 10);
65
- progressBar.css('width', progress + '%')
71
+ progressBar.css('width', progress + '%')
66
- },
72
+ },
67
- start: function (e) {
68
- submitButton.prop('disabled', true);
69
73
 
70
- progressBar.
71
- css('background', 'black').
72
- css('display', 'block').
73
- css('width', '0%').
74
- text("Loading...");
75
- },
76
- done: function(e, data) {
74
+ start: function (e) {
77
- submitButton.prop('disabled', false);
75
+ submitButton.prop('disabled', true);
78
- progressBar.text("Uploading done");
79
76
 
77
+ progressBar.
80
- // extract key and generate URL from response
78
+ css('background', 'black').
81
- var key = $(data.jqXHR.responseXML).find("Key").text();
82
- var url = '//' + form.data('host') + '/' + key;
79
+ css('display', 'block').
80
+ css('width', '0%').
81
+ text("Loading...");
82
+ },
83
83
 
84
- // create hidden field
85
- var input = $("<input />", { type:'hidden', name: fileInput.attr('name'), value: url })
86
- form.append(input);
87
- },
88
- fail: function(e, data) {
84
+ done: function(e, data) {
89
- submitButton.prop('disabled', false);
85
+ submitButton.prop('disabled', false);
86
+ progressBar.text("Uploading done");
90
87
 
88
+ // extract key and generate URL from response
89
+ var key = $(data.jqXHR.responseXML).find("Key").text();
90
+ var url = '//' + form.data('host') + '/' + key;
91
+
92
+ // create hidden field
93
+ var input = $("<input />", { type:'hidden', name: fileInput.attr('name'), value: url })
94
+ form.append(input);
95
+ $('.directUpload').submit(); //submit a form
96
+ },
97
+
98
+ fail: function(e, data) {
99
+ submitButton.prop('disabled', false);
100
+
91
- progressBar.
101
+ progressBar.
92
- css("background", "red").
102
+ css("background", "red").
93
- text("Failed");
103
+ text("Failed");
94
- }
104
+ }
95
- });
96
105
  });
97
106
  });
107
+ });
108
+
98
109
  ```
99
110
 
100
111
  ```Ruby
@@ -119,34 +130,7 @@
119
130
  ...
120
131
  ```
121
132
 
122
- ### 試したこと
123
-
124
- オンクリックアクションの部分を、以下のように変えて試してみました。
125
-
126
- ```javascript
127
- ...
128
- $('#_submit').on('click', function(){
129
- // crop のデータを取得
130
- $('#crop_img').cropper('getCroppedCanvas').toBlob(function (blob){
131
- var croppedFile = new File([blob], data.files[0].name);
132
- data.files[0] = croppedFile;
133
- data.originalFiles[0] = data.files[0];
134
- })
135
- data.submit();
136
- $('.directUpload').submit();
137
- });
138
- ...
139
- ```
140
-
141
- すると、オブジェクトは作成され、ページも遷移するのですが、アップロードされる画像が依然として元のままになってしまいます。
142
- また、画像を`<%= image_tag post.image_name %>`で描画しようとすると、以下のエラーが発生します。
143
- アセット名が空白になってしまうようです。
144
-
145
- ```
146
- The asset "" is not present in the asset pipeline.
147
- ```
148
-
149
- どうすれば、トリミング後の画像を、s3にアップしかつ描画することができるでしょうか?
133
+ どうすれば、トリミング後の画像を、s3にアップすることができるでしょうか?
150
134
  アドバイスをよろしくお願いいたします。
151
135
 
152
136