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

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

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

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

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

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

AWS(Amazon Web Services)

Amazon Web Services (AWS)は、仮想空間を機軸とした、クラスター状のコンピュータ・ネットワーク・データベース・ストーレッジ・サポートツールをAWSというインフラから提供する商用サービスです。

Q&A

解決済

1回答

2109閲覧

RailsからAWSのS3に画像をダイレクトアップロードする方法

yasukun252

総合スコア34

Ruby on Rails 5

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

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

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

AWS(Amazon Web Services)

Amazon Web Services (AWS)は、仮想空間を機軸とした、クラスター状のコンピュータ・ネットワーク・データベース・ストーレッジ・サポートツールをAWSというインフラから提供する商用サービスです。

0グッド

0クリップ

投稿2020/11/03 00:49

編集2020/11/03 03:02

RailsからAWSのS3に画像をダイレクトアップロードする方法について

RailsからAWSのS3に画像を直接アップロードする仕組みを実装しております。
そこで1つ質問なのですが、実装自体は問題なく完了したのですが、ローカル開発環境からAWSのS3に画像がアップロードされません。

本番環境はHerokuで運用を検討しておりますが、現在は開発のローカル環境で動かないです。

参考サイト:https://qiita.com/DaichiSaito/items/80e89f0c96d88afcc5ff
参考サイト:https://devcenter.heroku.com/articles/direct-to-s3-image-uploads-in-rails

以下は、実際のコードです。

GemfileFg gem 'aws-sdk', '~> 2'
model/users.rb class User < ApplicationRecord has_one :avatar, class_name: "UserAvatar", dependent: :destroy, autosave: true end
class UserAvatar < ApplicationRecord belongs_to :user, optional: true # このmモデルに「image :string」で画像を保存します。 end
users_controller.rb before_action :set_s3_direct_post, only: [:new, :edit, :create, :update] # 追加 # ユーザー新規登録フォーム def new if current_user redirect_to current_user else @user_form = UserForm.new end end # ユーザーの編集フォーム def edit @user_form = UserForm.new(User.find(params[:id])) end # ユーザーの新規作成 def create @user_form = UserForm.new @user_form.assign_attributes(params[:form]) if @user_form.save @user_form.user.send_activation_email redirect_to :signup_thanks else render :new end end # ユーザーの更新 def update @user_form = UserForm.new(@user) @user_form.assign_attributes(params[:form]) if @user_form.save redirect_to @user_form.user else render :edit end end private # 追加 def set_s3_direct_post @s3_direct_post = S3_BUCKET.presigned_post(key: "uploads/#{SecureRandom.uuid}/${filename}", success_action_status: '201', acl: 'public-read') end
forms/user_form.rb class UserForm include ActiveModel::Model attr_accessor :user, :name, :email, :gender, :inputs_destroy delegate :new_record?, :persisted?, :save, to: :user def initialize(user = nil) @user = user @user ||= User.new @user.build_avatar unless @user.avatar.present? end def assign_attributes(params = {}) @params = params user.assign_attributes(user_params) if params[:user][:avatar].present? avatar = avatar_params.fetch(:avatar) user.avatar.assign_attributes(avatar) end end private def user_params @params.require(:user).except(:avatar).permit( :name, :email, :gender, :profile_text, :password, :password_confirmation ) end def avatar_params @params.require(:user).slice(:avatar).permit( avatar: [ :image ] ) end end
views/users/edit.html.erb <%= form_for(@user_form, as: 'form', url: @user_form.user, html: { class: 'directUpload', data: { 'form-data' => (@s3_direct_post.fields), 'url' => @s3_direct_post.url, 'host' => URI.parse(@s3_direct_post.url).host } }) do |f| %> # 修正 <script> $(function() { $('.directUpload').find("input:file").each(function(i, elem) { var fileInput = $(elem); var form = $(fileInput.parents('form:first')); var submitButton = form.find('input[type="submit"]'); var progressBar = $("<div class='bar'></div>"); var barContainer = $("<div class='progress'></div>").append(progressBar); fileInput.after(barContainer); fileInput.fileupload({ fileInput: fileInput, url: form.data('url'), type: 'POST', autoUpload: true, formData: form.data('form-data'), paramName: 'file', // S3 does not like nested name fields i.e. name="user[avatar_url]" dataType: 'XML', // S3 returns XML if success_action_status is set to 201 replaceFileInput: false, progressall: function (e, data) { var progress = parseInt(data.loaded / data.total * 100, 10); progressBar.css('width', progress + '%') }, start: function (e) { submitButton.prop('disabled', true); progressBar. css('background', 'green'). css('display', 'block'). css('width', '0%'). text("Loading..."); }, done: function(e, data) { submitButton.prop('disabled', false); progressBar.text("Uploading done"); // extract key and generate URL from response var key = $(data.jqXHR.responseXML).find("Key").text(); var url = '//' + form.data('host') + '/' + key; // create hidden field var input = $("<input />", { type:'hidden', name: fileInput.attr('name'), value: url }) form.append(input); }, fail: function(e, data) { submitButton.prop('disabled', false); progressBar. css("background", "red"). text("Failed"); } }); }); }); </script>
config/initializers/aws.rb Aws.config.update({ region: 'ap-northeast-1', credentials: Aws::Credentials.new( '××××××××××××××××××××××××××××××××', # アクセスキー '××××××××××××××××××××××××××××××××' # シークレットキー ), }) S3_BUCKET = Aws::S3::Resource.new.bucket('×××××××××××××××××××××') # バケット名

以下二つのライブラリをダウンロードして、app/assets/javascripts配下に設置
https://raw.githubusercontent.com/jquery/jquery-ui/master/ui/widget.js
→app/assets/javascripts/jquery.ui.widget.js

https://raw.githubusercontent.com/blueimp/jQuery-File-Upload/master/js/jquery.fileupload.js
→app/assets/javascripts/z.jquery.fileupload.js

上記のように実装しましたが、画像をアップロードするとパラメータが以下のようになり、AWSのS3にアップロードされません。

Parameters: {"utf8"=>"✓", "authenticity_token"=>"hqGryq1RfJW1tv4XzWOK8xLs3Dazxs3h0u8+BScjb5N620ynmSg5Xnc5keXHl8QryVY4bolxrMAujB0vdfISTw==", "form"=>{"user"=>{"avatar"=>{"image"=>#<ActionDispatch::Http::UploadedFile:0x00007fa188674298 @tempfile=#<Tempfile:/var/folders/gd/52ml8dfd03v0jfgy6r2ls4x80000gn/T/RackMultipart20201103-12508-1pra42j.jpg>, @original_filename="2018-06-29 12.13.08.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"form[user][avatar][image]\"; filename=\"2018-06-29 12.13.08.jpg\"\r\nContent-Type: image/jpeg\r\n">}, "name"=>"test01", "email"=>"test01@example.com", "profile_text"=>""}}, "commit"=>"上記の内容で更新する", "id"=>"1"} ↳ app/forms/user_form.rb:5 User Update (0.2ms) UPDATE "users" SET "profile_text" = $1, "updated_at" = $2 WHERE "users"."id" = $3 [["profile_text", ""], ["updated_at", "2020-11-03 08:50:40.670585"], ["id", 1]] ↳ app/forms/user_form.rb:5 UserAvatar Create (0.6ms) INSERT INTO "user_avatars" ("user_id", "image", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["user_id", 1], ["image", "#<ActionDispatch::Http::UploadedFile:0x00007fa188674298>"], ["created_at", "2020-11-03 08:50:40.671752"], ["updated_at", "2020-11-03 08:50:40.671752"]] ↳ app/forms/user_form.rb:5 (0.5ms) COMMIT

imageの部分に#<ActionDispatch::Http::UploadedFile:0x00007fa188674298 @tempfile=#Tempfile:/var/folders/gd/52ml8dfd03v0jfgy6r2ls4x80000gn/T/RackMultipart20201103-12508-1pra42j.jpgと入っているのでソースコードは問題ないと思っております。

AWS管理画面からCORSは以下のように設定しました。

[ { "AllowedHeaders": [ "*" ], "AllowedMethods": [ "GET", "PUT", "POST" ], "AllowedOrigins": [ "http://localhost:3000" ], "ExposeHeaders": [], "MaxAgeSeconds": 3000 } ]

解決策などを教えて頂けますと幸いです。よろしくお願い致します。

参考サイト:https://qiita.com/DaichiSaito/items/80e89f0c96d88afcc5ff
参考サイト:https://devcenter.heroku.com/articles/direct-to-s3-image-uploads-in-rails

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

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

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

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

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

guest

回答1

0

自己解決

//= require jquery.ui.widget //= require z.jquery.fileupload

上記を記載することで解決しました。

投稿2020/11/03 03:09

yasukun252

総合スコア34

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問