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

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

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

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

AWS(Amazon Web Services)

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

Q&A

解決済

1回答

4866閲覧

rails S3にある画像ファイルをダウンロードしたい

hokosugi

総合スコア63

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

AWS(Amazon Web Services)

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

0グッド

0クリップ

投稿2018/10/11 00:34

前提・実現したいこと

ブラウザ側からS3にある画像をダウンロードできるボタンを作成したい。
ボタンでリンク先を指定するところまでは出来ています。

発生している問題

エラーが数過程発生していましたので確認のため段階を追って表示します。
初期の設定

controller

1def download 2 @index = params['id'] 3 myBacket = 'xxxx' 4 bucket = Aws::S3::Resource.new( 5 :region => 'ap-northeast-1', 6 :access_key_id => 'xxxx', 7 :secret_access_key => 'xxxx' 8 ).bucket(myBacket) 9 bucket.objects(:prefix => "name_no#{@index}",:max_keys => 10).each do |object| 10 data = open(URI.encode(object.public_url)) 11 send_file(data, filename: "name_no#{@index}.png", disposition: 'attachment', stream: true) 12 end

これで実行すると
403 Forbidden
となります。調べますとここ-ストックオーバーフローを参考にして

data = open(URI.encode(object.public_url))を

data = Net::HTTP.get(URI.parse(object.public_url))

これで実行すると、
Cannot read file <?xml version="1.0" encoding="UTF-8"?>
とActionController::MissingFile になります。
URI::parseやNet::HTTP.getなどのドキュメントを調べて推測になりますが、object.public_urlの文字列をどこかで置いてきた模様です。
ちなみにコンソールのエラー表示は

Started GET "/indices/5/download" for 61.245.214.147 at 2018-10-11 00:08:34 +0000 Cannot render console from 61.245.214.147! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255 Processing by IndicesController#download as HTML Parameters: {"id"=>"5"} Sent file <?xml version="1.0" encoding="UTF-8"?> <Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>F7976110C0985ADE</RequestId><HostId>DcgkiJv08lEsmQYqZ+YQscQK+EPhGjq2s0SFDXlZxq0P/tkiCGPGuVTZTdxCWnR3TYHe0LHlDwc=</HostId></Error> (0.6ms) Completed 500 Internal Server Error in 1646ms (ActiveRecord: 0.0ms) ActionController::MissingFile (Cannot read file <?xml version="1.0" encoding="UTF-8"?> <Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>F7976110C0985ADE</RequestId><HostId>DcgkiJv08lEsmQYqZ+YQscQK+EPhGjq2s0SFDXlZxq0P/tkiCGPGuVTZTdxCWnR3TYHe0LHlDwc=</HostId></Error>): app/controllers/indices_controller.rb:49:in `block in download' app/controllers/indices_controller.rb:43:in `download'

その他、念の為send_dataでもやってみましたが空のファイルが生成されるだけでした。

上記のような設定でどうすれば正常にダウンロードされるのかお教えください。

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

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

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

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

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

mather

2018/10/11 02:38 編集

403 Forbidden ということは「アクセス権限がない」ということになります。 S3のファイル権限はパブリックになっているのですか?
hokosugi

2018/10/11 06:58

ご回答・修正依頼ありがとうございます。確認のためアクセス権限の確認とパブリック設定からの実行をしましたがパブリックでも同じエラーで、アクセス権限もIAMにフルアクセス権を付与していますので問題はないようです。
mather

2018/10/11 07:00

IAMのフルアクセスはあくまでそのロールを持つユーザーにアクセス許可をしているだけなので、public_urlからはアクセスできません。
hokosugi

2018/10/11 07:04

ありがとうございます! 読み込みが甘いようですね、もう一度ドキュメント読んでトライしたいと思います。
guest

回答1

0

ベストアンサー

https://docs.aws.amazon.com/ja_jp/sdk-for-ruby/v3/api/Aws/S3/Client.html#get_object-instance_method

こちらの get_object でデータを取得してはどうでしょうか。
具体的な記述方法はここでは書きません。

投稿2018/10/11 07:03

mather

総合スコア6753

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

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

hokosugi

2018/10/11 07:12

なるほど、サンプルにダウンロードの記述がありますね。これを参考に書いてみたいと思います。 大変参考になりました。get_objectAPIは昨日、目を通してますが気が付きませんでした。まだ発想力というか気づきがないですね、がんばります。
hokosugi

2018/10/11 10:07

aws::s3.resourseクラスをclientに変更後、 bucket.list_objects(:bucket => myBacket, :prefix => "name_no#{@index}",:max_keys => 10).contents.each do |object| data = bucket.get_object(:bucket => myBacket, :key => object.key) get_objectのkeyハッシュにlist_objectsのobject.keyを与えることでダウンロード出来ました。 ただ、繰り返しにすると Render and/or redirect were called multiple times in this action. というエラーが出ますがこれはこれで今から勉強します。 なんとかダウンロード出来ましたので感謝です。ありがとうございます。
mather

2018/10/11 10:25

繰り返しは出来ませんね。一度ファイルダウンロード用のレスポンスと返したらそこでクライアントとのコネクションは終了しているので同じコネクションにレスポンスを送信することは出来ません。 典型的な例としてはサーバーサイドでzipファイルに圧縮して送信する方法ですね。
hokosugi

2018/10/11 10:32

やはりそうですか。なんのために繰り返し処理にしたのか・・・(2時間かかった)。 でも。面倒なエラー理解と検索の時間が省けましたこと有り難いです。 最終的にzipファイルでダウンロードと考えていましたので一歩進んだ感あります。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問