Rails:允许下载存储在S3上的文件,而不向用户显示实际的S3 URL

fut*_*ked 27 ruby-on-rails download amazon-s3

我有一个在Heroku上托管的Rails应用程序.该应用程序在Amazon S3上生成并存储PDF文件.用户可以下载这些文件以便在浏览器中查看或保存在他们的计算机上.

我遇到的问题是虽然可以通过S3 URL下载这些文件(如"https://s3.amazonaws.com/my-bucket/F4D8CESSDF.pdf"),但这显然不是一个好方法.它.不希望向用户公开关于后端的大量信息,更不用说上升的安全问题了.

是否有可能让我的应用以某种方式从控制器中的S3检索文件数据,然后为用户创建下载流,以便不暴露亚马逊URL?

Ser*_*yuk 56

您可以将s3对象创建为私有,并使用url_for方法为它们生成临时公共URL (aws-s3 gem).这样,您就不会通过应用程序服务器流式传输文件,这样可扩展性更高.它还允许基于会话的授权(例如,在您的应用程序中设计),跟踪下载事件等.

为此,将指向s3托管文件的直接链接更改为控制器/操作的链接,从而创建临时URL并重定向到它.像这样:

class HostedFilesController < ApplicationController

  def show
    s3_name = params[:id] # sanitize name here, restrict access to only some paths, etc
    AWS::S3::Base.establish_connection!( ... )
    url = AWS::S3::S3Object.url_for(s3_name, YOUR_BUCKET, :expires_in => 2.minutes)
    redirect_to url
  end

end
Run Code Online (Sandbox Code Playgroud)

在下载网址中隐藏亚马逊域通常使用DNS别名来完成.您需要创建子域的CNAME记录别名,例如downloads.mydomain,s3.amazonaws.com.然后你可以指定:server选项AWS::S3::Base.establish_connection!(:server => "downloads.mydomain", ...),S3 gem将用它来生成链接.


l4m*_*mpi 11

是的,这是可能的 - 只需使用Rails获取远程文件并将其临时存储在服务器上或直接从缓冲区发送.这个问题当然是您需要先获取文件才能将其提供给用户.请参阅此主题进行讨论,他们的解决方案是这样的:

#environment.rb
require 'open-uri'

#controller
def index
  data = open(params[:file])
  send_data data, :filename => params[:name], ...
end
Run Code Online (Sandbox Code Playgroud)

这个问题也有些相关.