使用 Rails 应用程序下载 S3 文件

Downloading S3 Files with Rails App

我目前正在尝试了解亚马逊 S3 网络服务的来龙去脉。今天的任务是成功下载上传的图片(在我的应用程序中称为asset)。我一直在松散地遵循 this tutorial 中的指导方针,努力从亚马逊服务器直接下载,但似乎遗漏了一些东西,因为什么都没有下载。

我在 assets_controller 中使用 get 方法如下:

def get
    asset = current_user.assets.find_by_id(params[:id])
    if asset
        File.open('file.png', 'w') do |file|
            s3 = AWS::S3::Client.new
            reap = s3.get_object({bucket_name: ENV['BUCKET'], key: URI.encode(asset.uploaded_file.path)}, target: file)
        end

    else
        flash[:error]="Don't be cheeky!  Mind your own assets"
    end
    redirect_to assets_path
end

我在这里没有看到任何错误,我的日志表明正在使用正确的密钥。但是,没有文件下载。一定有我不理解或不包括的东西。

另外几个可能有帮助的问题

  1. 我不完全确定 File.open 在这里做什么;它与下载的文件有关吗?
  2. 我添加了一个 redirect_to 命令来避免 missing_template 这会阻止触发下载吗?

您似乎可以很好地从 s3 下载文件(下载到 file.png),但您没有对其进行任何操作,因此它永远不会到达用户的浏览器。对 File.open 的调用将打开下载数据所在的文件。

Rails 提供了执行此操作的 send_file 方法(这算作渲染,因此在这种情况下您不需要调用重定向,否则会出现双重渲染错误)。

或者,您可以生成签名的 link 并将用户重定向到它。这完全避免了将文件下载到您的服务器。使用 SDK 的 v2,我相信您需要为此使用稍微高级的资源接口:

s3 = Aws::S3::Resource.new
s3.bucket(ENV['BUCKET']).object(object_key).presigned_url(:get, expires_in: 3600)

为对象生成一个下载link,有效期为一小时