アプリにダウンロードリンクがあり、ユーザーはそこからs3に保存されているファイルをダウンロードできます。これらのファイルは、次のようなURLで一般公開されます。
https://s3.amazonaws.com/:bucket_name/:path/:to/:file.png
ダウンロードリンクがコントローラーのアクションにヒットします。
class AttachmentsController < ApplicationController
def show
@attachment = Attachment.find(params[:id])
send_file(@attachment.file.url, disposition: 'attachment')
end
end
しかし、ファイルをダウンロードしようとすると、次のエラーが表示されます。
ActionController::MissingFile in AttachmentsController#show
Cannot read file https://s3.amazonaws.com/:bucket_name/:path/:to/:file.png
Rails.root: /Users/user/dev/Rails/print
Application Trace | Framework Trace | Full Trace
app/controllers/attachments_controller.rb:9:in `show'
このファイルは間違いなく存在し、エラーメッセージのURLで公開されています。
ユーザーにS3ファイルのダウンロードを許可するにはどうすればよいですか?
Webサーバーからファイルを送信するには、
s3からダウンロードする必要があります( @ nzajt's answer を参照)または
できますredirect_to @attachment.file.expiring_url(10)
あなたがより良いコントロールを持っているので、私はこのオプションが好きです。ユーザーをs3に送信していないため、一部のユーザーが混乱する可能性があります。
AttachmentsController
にダウンロードメソッドを追加するだけです
def download
data = open("https://s3.amazonaws.com/PATTH TO YOUR FILE")
send_data data.read, filename: "NAME YOU WANT.pdf", type: "application/pdf", disposition: 'inline', stream: 'true', buffer_size: '4096'
end
ルートを追加します
get "attachments/download"
これを処理する最良の方法は、期限切れになるS3 URLを使用することだと思います。他の方法には次の問題があります。
send_data
を使用しても、期待される「ブラウザダウンロード」は生成されません。download
コントローラーアクションが必要です。私の実装は次のようになります。
attachment.rb
def download_url
S3 = AWS::S3.new.buckets[ 'bucket_name' ] # This can be done elsewhere as well,
# e.g config/environments/development.rb
url_options = {
expires_in: 60.minutes,
use_ssl: true,
response_content_disposition: "attachment; filename=\"#{attachment_file_name}\""
}
S3.objects[ self.path ].url_for( :read, url_options ).to_s
end
<%= link_to 'Download Avicii by Avicii', attachment.download_url %>
それでおしまい。
それでも何らかの理由でdownload
アクションを保持したい場合は、これを使用してください:
あなたのattachments_controller.rb
def download
redirect_to @attachment.download_url
end
彼の指導に guilleva に感謝します。
public/system
フォルダーをAmazon S3に移行しました。上記のソリューションは役立ちますが、私のアプリはさまざまな種類のドキュメントを受け入れます。したがって、同じ動作が必要な場合、これは私に役立ちます:
@document = DriveDocument.where(id: params[:id])
if @document.present?
@document.track_downloads(current_user) if current_user
data = open(@document.attachment.expiring_url)
send_data data.read, filename: @document.attachment_file_name, type: @document.attachment_content_type, disposition: 'attachment'
end
ファイルは、attachment
オブジェクトのDriveDocument
フィールドに保存されています。これがお役に立てば幸いです。
以下は、私にとってうまくいったものです。 S3オブジェクトから生データを取得し、send_data
を使用してそれをブラウザに渡します。
ここにあるaws-sdk
gemドキュメントの使用 http://docs.aws.Amazon.com/AWSRubySDK/latest/AWS/S3/S3Object.html
フルコントローラー方式
def download
AWS.config({
access_key_id: "SECRET_KEY",
secret_access_key: "SECRET_ACCESS_KEY"
})
send_data(
AWS::S3.new.buckets["S3_BUCKET"].objects["FILENAME"].read, {
filename: "NAME_YOUR_FILE.pdf",
type: "application/pdf",
disposition: 'attachment',
stream: 'true',
buffer_size: '4096'
}
)
end