允许用户从S3存储中下载文件

时间:2023-02-06 00:05:40

Right now I am using Amazon S3 and Paperclip which is allowing my users to upload an image that is associated with the event they are creating. My ultimate goal is since others can view this event, to be able to click on the image and have it prompt a SAVE TO their computer. As of now, clicking the link will open the image in a browser window. I rather have it ask for them to download instead. All images only saved on S3, not local. Need to hide exposed s3 url as well if possible or camouflage it

现在我正在使用Amazon S3和Paperclip,它允许我的用户上传与他们正在创建的事件相关联的图像。我的最终目标是,因为其他人可以查看此事件,以便能够点击图像并让它提示保存到他们的计算机。截至目前,单击该链接将在浏览器窗口中打开图像。我宁愿让它要求他们下载。所有图像仅保存在S3上,而不是本地。如果可能,也需要隐藏暴露的s3网址或伪装它

Here is my current setup

这是我目前的设置

Index.html

的index.html

<%= link_to 'Download Creative', event.creative.url, class: "btn btn-info" %>

Event.rb

Event.rb

has_attached_file :creative,
                :styles => { :thumb => "150x150", :custcreative => "250x75" },
                :path => ":attachment/:id/:style.:extension",
                :s3_domain_url => "******.s3.amazonaws.com",
                :storage => :s3,
                :s3_credentials => Rails.root.join("config/s3.yml"),
                :bucket => '*****',
                :s3_permissions => :public_read,
                :s3_protocol => "http",
                :convert_options => { :all => "-auto-orient" },
                :encode => 'utf8'

Hoping someone can help me out.

希望有人可以帮助我。

5 个解决方案

#1


16  

To make this work, I've just added a new action in the controller, so in your case it could be:

为了使这项工作,我刚刚在控制器中添加了一个新动作,所以在你的情况下它可能是:

#routes
resources :events do
  member { get :download }
end

#index
<%= link_to 'Download Creative', download_event_path(event), class: "btn btn-info" %>

#events_controller
def download
  data = open(event.creative_url)
  send_data data.read, :type => data.content_type, :x_sendfile => true
end

EDIT: the correct solution for download controller action can be found here (I've updated the code above): Force a link to download an MP3 rather than play it?

编辑:下载控制器动作的正确解决方案可以在这里找到(我已经更新了上面的代码):强制链接下载MP3而不是播放它?

#2


26  

To avoid extra load to your app (saving dyno's time in Heroku), I would rather do something like this: add this method to your model with the attachment:

为了避免额外加载到您的应用程序(在Heroku中保存dyno的时间),我宁愿做这样的事情:使用附件将此方法添加到您的模型:

def download_url(style_name=:original)
  creative.s3_bucket.objects[creative.s3_object(style_name).key].url_for(:read,
      :secure => true,
      :expires => 24*3600,  # 24 hours
      :response_content_disposition => "attachment; filename='#{creative_file_name}'").to_s
end

And then use it in your views/controllers like this:

然后在你的视图/控制器中使用它,如下所示:

<%= link_to 'Download Creative', event.download_url, class: "btn btn-info" %>

#3


2  

Now in aws-sdk v2, there is a method :presigned_url defined in Aws::S3::Object, you can use this method to construct the direct download url for a s3 object:

现在在aws-sdk v2中,有一个方法:在Aws :: S3 :: Object中定义的presigned_url,你可以使用这个方法为s3对象构造直接下载url:

s3 = Aws::S3::Resource.new
# YOUR-OBJECT-KEY should be the relative path of the object like 'uploads/user/logo/123/pic.png'
obj = s3.bucket('YOUR-BUCKET-NAME').object('YOUR-OBJECT-KEY')
url = obj.presigned_url(:get, expires_in: 3600, response_content_disposition: "attachment; filename='FILENAME'")

then in your views, just use:

然后在你的意见中,只需使用:

= link_to 'download', url

#4


1  

event = Event.find(params[:id])
  data = open(event.creative.url)
  send_data data.read, :type => data.content_type, :x_sendfile => true, :url_based_filename => true
end

#5


0  

You need to set the "Content-Disposition" to "attachment" in your HTTP response header. I'm not a Rails developer - so just Google it and you'll see plenty of examples - but it probably looks something like this:

您需要在HTTP响应标头中将“Content-Disposition”设置为“attachment”。我不是Rails开发人员 - 所以只有谷歌它你会看到很多例子 - 但它可能看起来像这样:

    :content_disposition => "attachment"

or

要么

     ...
    :disposition => "attachment"

#1


16  

To make this work, I've just added a new action in the controller, so in your case it could be:

为了使这项工作,我刚刚在控制器中添加了一个新动作,所以在你的情况下它可能是:

#routes
resources :events do
  member { get :download }
end

#index
<%= link_to 'Download Creative', download_event_path(event), class: "btn btn-info" %>

#events_controller
def download
  data = open(event.creative_url)
  send_data data.read, :type => data.content_type, :x_sendfile => true
end

EDIT: the correct solution for download controller action can be found here (I've updated the code above): Force a link to download an MP3 rather than play it?

编辑:下载控制器动作的正确解决方案可以在这里找到(我已经更新了上面的代码):强制链接下载MP3而不是播放它?

#2


26  

To avoid extra load to your app (saving dyno's time in Heroku), I would rather do something like this: add this method to your model with the attachment:

为了避免额外加载到您的应用程序(在Heroku中保存dyno的时间),我宁愿做这样的事情:使用附件将此方法添加到您的模型:

def download_url(style_name=:original)
  creative.s3_bucket.objects[creative.s3_object(style_name).key].url_for(:read,
      :secure => true,
      :expires => 24*3600,  # 24 hours
      :response_content_disposition => "attachment; filename='#{creative_file_name}'").to_s
end

And then use it in your views/controllers like this:

然后在你的视图/控制器中使用它,如下所示:

<%= link_to 'Download Creative', event.download_url, class: "btn btn-info" %>

#3


2  

Now in aws-sdk v2, there is a method :presigned_url defined in Aws::S3::Object, you can use this method to construct the direct download url for a s3 object:

现在在aws-sdk v2中,有一个方法:在Aws :: S3 :: Object中定义的presigned_url,你可以使用这个方法为s3对象构造直接下载url:

s3 = Aws::S3::Resource.new
# YOUR-OBJECT-KEY should be the relative path of the object like 'uploads/user/logo/123/pic.png'
obj = s3.bucket('YOUR-BUCKET-NAME').object('YOUR-OBJECT-KEY')
url = obj.presigned_url(:get, expires_in: 3600, response_content_disposition: "attachment; filename='FILENAME'")

then in your views, just use:

然后在你的意见中,只需使用:

= link_to 'download', url

#4


1  

event = Event.find(params[:id])
  data = open(event.creative.url)
  send_data data.read, :type => data.content_type, :x_sendfile => true, :url_based_filename => true
end

#5


0  

You need to set the "Content-Disposition" to "attachment" in your HTTP response header. I'm not a Rails developer - so just Google it and you'll see plenty of examples - but it probably looks something like this:

您需要在HTTP响应标头中将“Content-Disposition”设置为“attachment”。我不是Rails开发人员 - 所以只有谷歌它你会看到很多例子 - 但它可能看起来像这样:

    :content_disposition => "attachment"

or

要么

     ...
    :disposition => "attachment"