2009-08-24 7 views
11

मेरे ऐप में, मुझे एक आवश्यकता है जो मुझे रोक रहा है।एक दूरस्थ स्रोत (रेल पर रूबी) को Send_File का उपयोग करके

मेरे पास S3 में संग्रहीत फ़ाइल है, और जब कोई उपयोगकर्ता मेरे ऐप में किसी लिंक पर क्लिक करता है, तो मैं डीबी में लॉग इन करता हूं, उन्होंने लिंक पर क्लिक किया है, एक करके अपने 'डाउनलोड क्रेडिट' भत्ता घटाएं और फिर मैं चाहता हूं फ़ाइल डाउनलोड करने के लिए संकेत दें।

मैं नहीं है बस फाइल करने के लिए उपयोगकर्ता रीडायरेक्ट करने के लिए है क्योंकि यह S3 में संग्रहीत चीज़ें चाहते हैं और मैं उन्हें स्रोत फ़ाइल के लिंक के लिए

(ताकि मैं ईमानदारी और पहुंच बनाए रख सकते) नहीं करना चाहते

ऐसा लगता है कि send_file() दूरस्थ स्रोत फ़ाइल के साथ काम नहीं करेगा, कोई भी मणि या उपयुक्त कोड की सिफारिश करेगा जो यह करेगा?

+0

संभावित डुप्लिकेट [ब्राउज़र में फ़ाइल को डाउनलोड करने के लिए \ _data भेजने के लिए कैसे मजबूर करें?] (Http://stackoverflow.com/questions/7337508/how-to-force-send-data-to-download- फ़ाइल-इन-द-ब्राउजर) –

उत्तर

9

आपको एस 3 बाल्टी/ऑब्जेक्ट से इसे पढ़ने के दौरान फ़ाइल सामग्री को स्ट्रीम करने की आवश्यकता होगी।

आप इस तरह AWS::S3 पुस्तकालय कुछ काम कर सकते हैं का उपयोग करते हैं:

send_file_headers!(:length=>S3Object.about(<s3 object>, <s3 bucket>)["content-length"], :filename=><the filename>) 
render :status => 200, :text => Proc.new { |response, output| 
    S3Object.stream(<s3 object>, <s3 bucket>) do |chunk| 
    output.write chunk 
    end 
} 

इस कोड को ज्यादातर प्रपत्र send_file कोड है जो अपने आप में ही स्थानीय फ़ाइलों या फ़ाइल की तरह वस्तुओं

N.B. लिए काम करता है नकल की जाती है मैं रेलवे प्रक्रिया से फ़ाइल की सेवा करने के खिलाफ किसी भी तरह सलाह दूंगा। यदि आपके उपयोग के मामले में संभव/स्वीकार्य है तो मैं बाल्टी से निजी डेटा की सेवा के लिए प्रमाणीकृत GET का उपयोग करूंगा।

प्रमाणीकृत GET का उपयोग करके आप बाल्टी और इसकी वस्तुओं को निजी रख सकते हैं, जबकि एक प्रमाणीकरण हस्ताक्षर टोकन समेत एक URL को क्राफ्ट करके एक विशिष्ट ऑब्जेक्ट सामग्री को पढ़ने की अस्थायी अनुमति की अनुमति दे रही है। उपयोगकर्ता को केवल प्रमाणीकृत यूआरएल पर रीडायरेक्ट किया जाता है, और टोकन को कुछ ही मिनटों के लिए वैध बनाया जा सकता है।

ऊपर उल्लेख किया एडब्ल्यूएस का उपयोग :: S3 आप इस तरह से एक प्रमाणीकृत प्राप्त यूआरएल प्राप्त कर सकते हैं:

time_of_exipry = Time.now + 2.minutes 
S3Object.url_for(<s3 object>, <s3 bucket>, 
        :expires => time_of_exipry) 
+0

S3Ojbect.url_for सर्वोत्तम दृष्टिकोण की तरह दिखता है – klochner

+2

हमने एक वर्ष के लिए रीडायरेक्ट का उपयोग किया, लेकिन अब हम वास्तव में सफारी/मैक को काम करना चाहते हैं: http://stackoverflow.com/questions/1995589/एचटीएमएल 5-ऑडियो-सफारी-लाइव-प्रसारण-बनाम नहीं send_file_headers!निजी है, न तो send_data या send_file दूरस्थ फ़ाइलों को स्वीकार करता है; कामकाज योग्य लेकिन केवल FYI – kain

+0

मुझे लगता है कि जिस तरह से आप time_of_expiry उत्पन्न करते हैं, वास्तव में काम नहीं करेगा, आपको यह करने की ज़रूरत है: 'time_of_expiry = 2.minutes.from_now.to_i' – Raphael

3

आप एक गैर सरकारी निर्देशिका के लिए S3 से फ़ाइल को पढ़ने और लिख सकते हैं स्थानीय स्तर पर है, तो का उपयोग सामग्री की सेवा के लिए एक्स-सेंडफाइल (अपाचे) या एक्स-एक्सेल-रीडायरेक्ट (nginx)।

nginx के लिए आप अपने config में निम्नलिखित की तरह कुछ में शामिल हैं:


    response.headers['Content-Type'] = your_content_type 
    response.headers['Content-Disposition'] = "attachment; filename=#{your_file_name}" 
    response.headers['Cache-Control'] = "private" 
    response.headers['X-Accel-Redirect'] = path_to_your_file 
    render :nothing=>true 

प्रक्रिया का एक अच्छा writeup here है:


      location /private { 
           internal; 
           alias /path/to/private/directory/; 
      } 
फिर अपने रेल नियंत्रक में

, आप निम्न कर

+0

जो आप कहते हैं वह सही है लेकिन स्थानीय फाइलों के बिना ऐसा करने का कोई तरीका होगा वेब सर्वर? मामले में समस्या यह है कि फाइलें एस 3 वेब सेवा पर संग्रहीत हैं। – LucaM

+1

मुझे नहीं लगता कि आप लोगों को प्रति-उपयोगकर्ता सीधे आपकी S3 फ़ाइलों तक पहुंच प्रदान कर सकते हैं जब तक कि उनके पास अपना स्वयं का S3 खाता न हो। आपको S3 से फ़ाइलों को अपने स्थानीय सर्वर पर डाउनलोड करना होगा और वहां से भेजना होगा। – klochner

+0

s3 फ़ाइलें अक्सर सार्वजनिक हैं, केवल obfuscated यूआरआई का उपयोग कर। लगता है कि आप जिस प्रभाव को हासिल करने की कोशिश कर रहे हैं, वह फाइलों की प्रतिलिपि किए बिना किया जा सकता है, यहां चर्चा देखें: http://www.ruby-forum.com/topic/132214। आपको 2 चरणों को करना होगा, हालांकि: लॉगिन करें, और फिर फ़ाइल अनुरोध भेजें। – austinfromboston

3

temp फ़ाइल का उपयोग कर पूर्ण छवि डाउनलोड विधि (परीक्षण रेल 3.2):

def download 
    @image = Image.find(params[:image_id]) 

    open(@image.url) {|img| 
    tmpfile = Tempfile.new("download.jpg") 
    File.open(tmpfile.path, 'wb') do |f| 
     f.write img.read 
    end 
    send_file tmpfile.path, :filename => "great-image.jpg" 
    } 
end 
+0

एक आकर्षण की तरह काम करता है! टेम्पलफाइल स्वचालित रूप से जीसी पर हटा दिया जाता है! –

संबंधित मुद्दे