2012-10-17 5 views
14

Hiện tại tôi đang sử dụng Amazon S3 và Paperclip cho phép người dùng của tôi tải lên hình ảnh được liên kết với sự kiện họ đang tạo. Mục tiêu cuối cùng của tôi là vì những người khác có thể xem sự kiện này, để có thể nhấp vào hình ảnh và yêu cầu nó được lưu vào máy tính của họ. Hiện tại, việc nhấp vào liên kết sẽ mở hình ảnh trong cửa sổ trình duyệt. Thay vào đó, tôi yêu cầu họ tải xuống. Tất cả các hình ảnh chỉ được lưu trên S3, chứ không phải cục bộ. Cần phải giấu url s3 tiếp xúc cũng như nếu có thể hoặc ngụy trang nóCho phép người dùng tải xuống tệp từ bộ nhớ S3

Đây là thiết lập hiện tại của tôi

index.html

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

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' 

Hy vọng ai đó có thể giúp tôi.

Trả lời

16

Để làm công việc này, tôi đã chỉ cần thêm một hành động mới trong bộ điều khiển, vì vậy trong trường hợp của bạn nó có thể là:

#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: giải pháp đúng cho hành động tải về bộ điều khiển có thể được tìm thấy ở đây (tôi đã cập nhật mã ab ove): Force a link to download an MP3 rather than play it?

+0

Bạn đang tuyệt vời! Lấy ý tưởng này và thay đổi nó một chút để làm việc cho ứng dụng của tôi: – RubyNewbie

0

Bạn cần đặt "Content-Disposition" thành "tệp đính kèm" trong tiêu đề phản hồi HTTP của bạn. Tôi không phải là một nhà phát triển Rails - vì vậy chỉ cần Google nó và bạn sẽ thấy rất nhiều ví dụ - nhưng nó có thể trông giống như sau:

:content_disposition => "attachment" 

hoặc

 ... 
    :disposition => "attachment" 
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 
26

Để tránh phụ tải để ứng dụng của bạn (tiết kiệm thời gian Dyno trong Heroku), tôi thà làm một cái gì đó như thế này: thêm phương pháp này để mô hình của bạn với các tập tin đính kèm:

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 

Và sau đó sử dụng nó trong quan điểm của bạn/bộ điều khiển như thế này:

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

Genius! Điều này làm việc tuyệt vời để tải xuống ngay từ S3, không buộc phải quá trình Ruby, không tải xuống máy chủ trước và không gửi người dùng đi. Tuyệt vời –

+0

Plus, nó không yêu cầu một hành động khác trong bộ điều khiển. –

+1

Đọc rất nhiều câu trả lời khác để tải xuống các tệp từ s3 (các giải pháp send_data và send_file ở mọi nơi), nhưng điều này là súc tích nhất và chỉ cần làm việc ngay lập tức với số lượng mã ít nhất. –

2

Bây giờ trong AWS-sdk v2, có một phương pháp: presigned_url quy định tại Aws :: S3 :: Object, bạn có thể sử dụng phương pháp này để xây dựng trực tiếp xuống url tải cho một đối tượng s3:

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'") 

sau đó trong quan điểm của bạn, chỉ cần sử dụng:

= link_to 'download', url