使用Send_File到远程源(Ruby on Rails)

在我的应用程序中,我有一个要求让我感到难过。

我有一个存储在S3中的文件,当用户点击我的应用程序中的链接时,我登录他们点击链接的数据库,将他们的“下载信用”限额减少一个,然后我想提示该文件下载。

我不只是想将用户重定向到该文件,因为它存储在S3中,我不希望它们具有源文件的链接(这样我可以保持完整性和访问权限)

看起来send_file()不能使用远程源文件,任何人都推荐gem或合适的代码来执行此操作?

在从S3存储桶/对象读取文件内容时,您需要将文件内容流式传输给用户。

如果您使用AWS :: S3库,则可能会这样:

send_file_headers!( :length=>S3Object.about(, )["content-length"], :filename=> ) render :status => 200, :text => Proc.new { |response, output| S3Object.stream(, ) do |chunk| output.write chunk end } 

此代码主要通过send_file代码复制,该代码本身仅适用于本地文件或类文件对象

NB无论如何我会建议不要从rails进程本身提供文件。 如果您的用例可能/可接受,我将使用经过身份validation的GET来提供来自存储桶的私有数据。

使用经过身份validation的GET,您可以将存储桶及其对象保持为私有,同时允许通过制作包含身份validation签名令牌的URL来临时读取特定对象内容的权限。 用户只需重定向到经过身份validation的URL,该令牌可以在几分钟内生效。

使用上面提到的AWS :: S3,您可以通过以下方式获取经过身份validation的GET URL:

  time_of_exipry = Time.now + 2.minutes S3Object.url_for(, , :expires => time_of_exipry) 

您可以从S3读取文件并将其本地写入非公共目录,然后使用X-Sendfile(apache)或X-Accel-Redirect(nginx)来提供内容。

对于nginx,您将在配置中包含以下内容:

 location /private { internal; alias /path/to/private/directory/; } 

然后在rails控制器中执行以下操作:

 response.headers['Content-Type'] = your_content_type response.headers['Content-Disposition'] = "attachment; filename=#{your_file_name}" response.headers['Cache-Control'] = "private" response.headers['X-Accel-Redirect'] = path_to_your_file render :nothing=>true 

这里有一个很好的写作过程

使用临时文件的完整图像下载方法(测试的rails 3.2):

 def download @image = Image.find(params[:image_id]) open(@image.url) {|img| tmpfile = Tempfile.new("download.jpg") File.open(tmpfile.path, 'wb') do |f| f.write img.read end send_file tmpfile.path, :filename => "great-image.jpg" } end