2010-02-26 22 views
15

पर संग्रहीत सभी पेपरक्लिप अनुलग्नक ज़िप करें पेपरक्लिप रेल के लिए एक महान अपलोड प्लगइन है। स्थानीय फाइल सिस्टम या अमेज़ॅन एस 3 पर अपलोड संग्रहीत करना अच्छी तरह से काम करता है। मैं सिर्फ स्थानीयहोस्ट पर स्टोर फाइलों को मानता हूं, लेकिन इस ऐप के लिए एस 3 का उपयोग आवश्यक है क्योंकि इसे हेरोकू पर होस्ट किया जाएगा।एस 3

मैं एक ज़िप्ड डाउनलोड में एस 3 से अपने सभी अपलोड/अनुलग्नक प्राप्त करने के बारे में कैसे जाउंगा?

स्थानीय फाइल सिस्टम से फ़ाइलों का एक ज़िप प्राप्त करना सीधे आगे लगता है। यह एस 3 से फाइलें प्राप्त कर रहा है जिसने मुझे परेशान किया है। मुझे लगता है कि रूबीजिप यूआरएल द्वारा संदर्भित फाइलों को संभालने के तरीके से ऐसा कुछ कर सकता है। मैंने विभिन्न दृष्टिकोणों की कोशिश की है लेकिन त्रुटियों से बचने के लिए प्रतीत नहीं हो सकता है।

format.zip { 
       registrations_with_attachments = Registration.find_by_sql('SELECT * FROM registrations WHERE abstract_file_name NOT LIKE ""') 
       headers['Cache-Control'] = 'no-cache' 
       tmp_filename = "#{RAILS_ROOT}/tmp/tmp_zip_" << 
           Time.now.to_f.to_s << 
           ".zip" 

       # rubyzip gem version 0.9.1 
       # rdoc http://rubyzip.sourceforge.net/     
       Zip::ZipFile.open(tmp_filename, Zip::ZipFile::CREATE) do |zip| 
        #get all of the attachments 

        # attempt to get files stored on S3 
        # FAIL 
        registrations_with_attachments.each { |e| zip.add("abstracts/#{e.abstract.original_filename}", e.abstract.url(:original, false)) } 
        # => No such file or directory - http://s3.amazonaws.com/bucket/original/abstract.txt 
        # Should note that these files in S3 bucket are publicly accessible. No ACL. 

        # works with local storage. Thanks to Henrik Nyh 
        # registrations_with_attachments.each { |e| zip.add("abstracts/#{e.abstract.original_filename}", e.abstract.path(:original)) } 
       end  

       send_data(File.open(tmp_filename, "rb+").read, :type => 'application/zip', :disposition => 'attachment', :filename => tmp_filename.to_s) 
       File.delete tmp_filename 
      } 
+0

सोच यहाँ समाधान एडब्ल्यूएस-S3 मणि को उपयोग करने के लिए है अगर (मैं प्रारंभिक सवाल के साथ स्थिरता के लिए प्रारंभिक कोड चर नाम रखा है) बाल्टी में सभी फाइलें पाएं और पेपरक्लिप का उपयोग न करें? – chaserx

+0

आप लगभग निश्चित रूप से url() के बजाय to_file() का उपयोग करना चाहते हैं। – vladr

+0

हाँ। मैं भी इसके बावजूद। यह त्रुटि देता है। पेपरक्लिप :: टेम्पफाइल को स्ट्रिंग में परिवर्तित नहीं कर सकता – chaserx

उत्तर

11

आप लगभग निश्चित रूप से e.abstract.to_file.path बजाय e.abstract.url(...) उपयोग करना चाहते हैं।

देखें:

अद्यतन

(एक TempFile लौटना चाहिए) changelog से:

3.0.1 में नया:

  • एपीआई परिवर्तन: #to_file हटा दिया गया है। इसके बजाय #copy_to_local_file विधि का उपयोग करें।
+0

धन्यवाद, व्लाद का उपयोग करें। ऐसा लगता है कि अब काम करता है। – chaserx

+0

पेपरक्लिप> 3.0, .to_file को यह उत्तर अपडेट कर दिया गया है :( –

+0

@ डेविड मॉरिसियो मैंने जवाब अपडेट किया। – vladr

2

@ vlard का समाधान ठीक है। हालांकि मैंने to_file के साथ कुछ मुद्दों में भाग लिया है। यह एक tempfile बनाता है और कचरा कलेक्टर ज़िप फ़ाइल में जोड़ा जाने से पहले फ़ाइल (कभी कभी) फ़ाइल हटा देता है। इसके लिए, मुझे यादृच्छिक Errno::ENOENT: No such file or directory त्रुटियां मिल रही हैं।

तो मैं अब निम्नलिखित कोड का उपयोग कर रहा

format.zip { 
      registrations_with_attachments = Registration.find_by_sql('SELECT * FROM registrations WHERE abstract_file_name NOT LIKE ""') 
      headers['Cache-Control'] = 'no-cache' 

      #please note that using nanoseconds option in strftime reduces the risks concerning the situation where 2 or more users initiate the download in the same time 
      tmp_filename = "#{RAILS_ROOT}/tmp/tmp_zip_" << 
          Time.now.strftime('%Y-%m-%d-%H%M%S-%N').to_s << 
          ".zip" 

      # rubyzip gem version 0.9.4     
      zip = Zip::ZipFile.open(tmp_filename, Zip::ZipFile::CREATE) 
      zip.close 

      registrations_with_attachments.each { |e| 
       file_to_add = e.file.to_file 
       zip = Zip::ZipFile.open(tmp_filename) 
       zip.add("abstracts/#{e.abstract.original_filename}", file_to_add.path) 
       zip.close 
       puts "added #{file_to_add.path} to #{tmp_filename}" #force garbage collector to keep the file_to_add until after the file has been added to zip 
      } 

      send_data(File.open(tmp_filename, "rb+").read, :type => 'application/zip', :disposition => 'attachment', :filename => tmp_filename.to_s) 
      File.delete tmp_filename 
     } 
+0

क्या आप समझा सकते हैं कि आपका समाधान कचरा कलेक्टर को इंतजार क्यों करता है? धन्यवाद! – Jared

+1

मैं समझा नहीं सकता कि यह क्यों काम करता है, लेकिन यह पुष्टि कर सकता है कि मेरे पास एक ही समस्या थी और यह इसे ठीक कर दिया! – Oll

+0

File.open विधि में 'b +' क्या है? मेरा मानना ​​है कि केवल 'आर (+) ',' डब्ल्यू (+) 'और' ए (+) 'है। – Marc