2012-09-05 12 views
26

पर वास्तविक S3 यूआरएल दिखाए बिना एस 3 पर संग्रहीत फ़ाइलों को डाउनलोड करने की अनुमति दें मेरे पास हेरोकू पर एक रेल एप्लिकेशन होस्ट किया गया है। ऐप अमेज़ॅन एस 3 पर पीडीएफ फाइलें उत्पन्न और स्टोर करता है। उपयोगकर्ता इन फ़ाइलों को अपने ब्राउज़र में देखने या अपने कंप्यूटर पर सहेजने के लिए डाउनलोड कर सकते हैं।रेल: उपयोगकर्ता को

समस्या मैं कर रहा हूँ कि हालांकि इन फ़ाइलों के डाउनलोड करने S3 यूआरएल द्वारा संभव है ("https://s3.amazonaws.com/my-bucket/F4D8CESSDF.pdf" की तरह), यह स्पष्ट रूप से नहीं है एक है ऐसा करने का अच्छा तरीका। उपयोगकर्ता को बैकएंड के बारे में इतनी सारी जानकारी का पर्दाफाश करना वांछनीय नहीं है, जो उठने वाले सुरक्षा मुद्दों का उल्लेख न करें।

क्या यह संभव है कि मेरा ऐप किसी भी तरह से नियंत्रक में S3 से फ़ाइल डेटा पुनर्प्राप्त कर सके, फिर उपयोगकर्ता के लिए एक डाउनलोड स्ट्रीम बनाएं, ताकि अमेज़ॅन यूआरएल का खुलासा न हो?

+0

आप स्पष्ट रूप से इसे डाउनलोड और फिर इसे वापस उपयोगकर्ता के लिए धारा, लेकिन यह विशेष रूप से तेजी से नहीं होगा सकते हैं। –

उत्तर

9

हां, यह संभव है - बस दूरस्थ फ़ाइल को रेल के साथ लाएं और या तो इसे अस्थायी रूप से अपने सर्वर पर संग्रहीत करें या इसे सीधे बफर से भेजें। इसके साथ समस्या यह तथ्य है कि उपयोगकर्ता को इसे सेवा देने से पहले आपको फ़ाइल को पहले लाने की आवश्यकता है।

#environment.rb 
require 'open-uri' 

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

This issue is also somewhat related: चर्चा के लिए this thread देखें, उनके समाधान कुछ इस तरह है।

+0

यह आसान साबित हुआ, धन्यवाद। डीईएफ़ file_name = params [ "file_id"] ".pdf" डेटा डाउनलोड = खुला ("https://s3.amazonaws.com/#{ENV['S3_BUCKET_NAME']}/: यह मेरा वास्तविक क्रियान्वयन है # {file_name} ") send_data data.read,: filename => file_name,: type =>" application/pdf ",: disposition => 'attachment', : stream => 'true',: buffer_size => ' 4096 ' अंत मैंने इस समस्या के समाधान के रूप में आपका समाधान स्वीकार कर लिया है क्योंकि यह लागू करने के लिए सबसे आसान है। – futureshocked

+0

सर्ज का एक भी अच्छा है, रेल एप्लिकेशन को डाउनलोड को संभालने से मुक्त करने के लाभ के साथ, इसे काम करने के लिए बस थोड़ा और काम चाहिए। – futureshocked

+0

बस दूसरों को पता है, इसके साथ दो मुद्दे हैं: 1) यह सर्वर पर और फिर उपयोगकर्ता को डाउनलोड करता है, जिसमें कुछ समय लग सकता है; और 2) उपयोगकर्ता के लिए अनुभव वह नहीं है जो वे उम्मीद करते हैं। अपने ब्राउज़र में डाउनलोड करने के बजाय, ऐसा लगता है, जैसे, यह कुछ लोड हो रहा है। आगे की चर्चा के लिए http://stackoverflow.com/a/23161355/293280 देखें। –

51

आप अपनी एस 3 वस्तुओं को निजी के रूप में बना सकते हैं और url_for विधि (aws-s3 मणि) के साथ अस्थायी सार्वजनिक यूआरएल उत्पन्न कर सकते हैं। इस तरह आप अपने ऐप सर्वर के माध्यम से फ़ाइलों को स्ट्रीम नहीं करते हैं, जो अधिक स्केलेबल है। यह सत्र आधारित प्राधिकरण (जैसे आपके ऐप में तैयार),

ऐसा करने के लिए, एस 3 होस्टेड फ़ाइलों के लिए सीधे लिंक को नियंत्रक/क्रिया के लिंक में बदलें जो अस्थायी यूआरएल बनाता है और इसे पुनर्निर्देशित करता है। इस तरह: डाउनलोड यूआरएल में अमेज़न डोमेन के

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 

छिपा आमतौर पर डीएनएस अलियासिंग के साथ किया जाता है। आपको create CNAME record aliasing your subdomain की आवश्यकता है, उदा। downloads.mydomain, s3.amazonaws.com पर। फिर आप AWS::S3::Base.establish_connection!(:server => "downloads.mydomain", ...) में :server विकल्प निर्दिष्ट कर सकते हैं और एस 3 मणि लिंक बनाने के लिए इसका उपयोग करेंगे।

+0

सर्ज, मैंने आपकी विधि की कोशिश की। यह काम करता है, हालांकि यूआरएल इस तरह दिखता है: http://s3.amazonaws.com/my-bucket/F4D8CED0.pdf?AWSAccessKeyId=my-actual-key&Expires=1346904098&Signature=Wo7wYH6Ek%2FBot3wd2xYbGt4ybSU%3D। मैं आदर्श रूप से देखना चाहता हूं कि अमेज़ॅन का कोई उल्लेख नहीं है, लेकिन "http://mydomain.com/download/file.pdf जैसे कुछ क्या यह संभव है? – futureshocked

+0

आप सीएनएन के साथ बहुत करीब आ सकते हैं, लेकिन यह 'something.mydomain.com/path/file.pdf' की तरह अधिक होगा। मैंने इसे प्रतिबिंबित करने के लिए उत्तर अपडेट किया है। –

+0

बहुत अच्छा समाधान, धन्यवाद सर्ज। – futureshocked

-1

सबसे पहले आपको अपने डोमेन में एक CNAME बनाने की आवश्यकता है, जैसे here समझाएं।

दूसरा आपको उसी नाम के साथ एक बाल्टी बनाने की आवश्यकता है जिसे आपने CNAME में रखा था।

और आप अपने config/initializers/carrierwave.rb में इस विन्यास को जोड़ने की जरूरत है समाप्त करने के लिए:

CarrierWave.configure do |config| 
    ... 
    config.asset_host   = 'http://bucket_name.your_domain.com' 
    config.fog_directory  = 'bucket_name.your_domain.com' 
    ... 
end 
संबंधित मुद्दे