使用由send_file下载从Amazon S3文件?(Using send_file to dow

2019-06-18 01:06发布

我在我的应用程序下载链接,从哪些用户可以下载它们存储在S3上的文件。 这些文件将在网址看起来像公开访问

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'

文件肯定存在,并且是在错误消息中的网址公开访问。

如何让用户下载S3文件?

Answer 1:

为了从您的Web服务器发送一个文件,

  • 你需要从S3(见下载@ nzajt的答案 )或

  • 你可以redirect_to @attachment.file.expiring_url(10)



Answer 2:

您还可以使用send_data

因为你有更好的控制,我喜欢这个选项。 你是不是用户发送到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"


Answer 3:

让事情变得简单为用户

我认为处理这个最好的方法是使用过期S3网址。 其他的方法有以下问题:

  • 该文件下载到服务器,然后再提供给用户。
  • 使用send_data不会产生预期的“浏览器下载”。
  • 挤占Ruby进程。
  • 需要额外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他的指导。



Answer 4:

我刚刚迁移我的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对象。 我希望这有帮助。



Answer 5:

下面就是结束了,我运作良好。 从S3对象获取原始数据,然后使用send_data来传递到浏览器。

使用aws-sdk发现这里的宝石文档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


文章来源: Using send_file to download a file from Amazon S3?