2010-12-03 17 views
5

मेरे पास रूबी एप्लिकेशन है, और मुझे मौजूदा ज़िप फ़ाइल को संशोधित करने की आवश्यकता है।मैं केवल ज़िप में एक ज़िप फ़ाइल को कैसे संशोधित कर सकता हूं?

मैं ज़िप फ़ाइल को मेमोरी में बनाना चाहता हूं और फ़ाइलों को फाइल सिस्टम में कभी भी लिखने के बिना बाइट्स को स्ट्रीम करना चाहता हूं। अगर मैं हेरोोकू पर इसे होस्ट करना समाप्त करता हूं तो मुझे नहीं लगता कि मैं फाइल सिस्टम पर लिख सकता हूं। क्या किसी को ऐसा करने का तरीका पता है?

मैंने Zip::ZipFile पर देखा लेकिन ऐसा लगता है कि यह हमेशा फाइल सिस्टम को लिखना चाहता है। मुझे लगता है कि "जावा कार्यान्वयन के आधार पर" मैं संकुचित फ़ाइल के बाइट्स प्राप्त करने में सक्षम हूं, जिसे आप जावा में कर सकते हैं, लेकिन मुझे ऐसा करने का कोई तरीका नहीं दिख रहा है।


संपादित करें:

क्या मैं पूछ रहा हूँ मूल रूप से इस रूप में ही है, लेकिन अजगर के बजाय रूबी के लिए: Function to create in-memory zip file and return as http response

उत्तर

3

यहाँ एक blog post जो इस मुद्दे के साथ संबंधित है। यह Tempfile का उपयोग करता है और मेरे लिए एक उत्कृष्ट समाधान की तरह लगता है (हालांकि कुछ उपयोगी अतिरिक्त चर्चा के लिए टिप्पणियों के माध्यम से पढ़ें)।

एक उदाहरण है, पद से:

def download_zip(image_list) 
    if !image_list.blank? 
    file_name = "pictures.zip" 
    t = Tempfile.new("my-temp-filename-#{Time.now}") 
    Zip::ZipOutputStream.open(t.path) do |z| 
     image_list.each do |img| 
     title = img.title 
     title += ".jpg" unless title.end_with?(".jpg") 
     z.put_next_entry(title) 
     z.print IO.read(img.path) 
     end 
    end 
    send_file t.path, :type => 'application/zip', 
         :disposition => 'attachment', 
         :filename => file_name 
    t.close 
    end 
end 

यह समाधान should play nice with Heroku

+0

Tempfile फ़ाइल बनाने के लिए नहीं है? –

+1

हां यह करता है, मार्क (जब तक आपकी अस्थायी निर्देशिका स्मृति में नहीं रहती), लेकिन रैली 25rs ने यह निर्दिष्ट नहीं किया कि वह फ़ाइल क्यों नहीं बनाना चाहता था।मैं एक धारणा बना रहा हूं जिसने मुझे एक समाधान के लिए प्रेरित किया है कि ए) हेरोकू पर ठीक काम करेगा, और बी) एक फाइल बनाता है, लेकिन एक रैली25rs को फिर से सोचना नहीं होगा, और ओएस द्वारा इसे साफ किया जाएगा। अगर यह उसकी मूल समस्या का समाधान नहीं करता है तो मैं जानना चाहता हूं। –

+0

मुझे लगता है कि मेरा मूल उद्देश्य केवल पढ़ने-योग्य फाइलों के इस हेरोकू बाधा के आसपास काम करना था: http://docs.heroku.com/constraints#read-only-filesystem लेकिन मुझे लगता है कि मैं temp फ़ाइल को/tmp पर लिख सकता हूं यदि आवश्यक हो तो निर्देशिका। मैं रूबी के लिए काफी नया हूं, लेकिन जावा में इसे लागू करना पूरी फाइल को मेमोरी बफर में रखना बहुत आसान होगा, इसलिए मुझे लगा कि यह रूबी में भी होता। सहायता के लिए धन्यवाद! – CodingWithSpike

1

आप हमेशा स्ट्रिंगियो हैंडल के उपयोग की अनुमति देने के लिए new और open ज़िप :: ZipFile के तरीकों को पैच कर सकते हैं, फिर अपने I/O को सीधे स्मृति में करें।

1

यहां अपने स्वयं के प्रश्न का उत्तर देने का प्रस्ताव देने के लिए, मुझे लगता है कि मैं जो करने की कोशिश कर रहा था उससे बेहतर फिट बैठता है। यह विधि वास्तव में कोई फ़ाइल नहीं बनाता है (कोई अस्थायी फ़ाइल नहीं)।

चूंकि ज़िपफाइल विस्तारित करता है, और वास्तव में ज़िपपेंट्रल डायरेक्टरी के आस-पास सुविधा विधियों का एक समूह है, तो आप सीधे ZipFile के बजाय ZipCentralDirectory के साथ काम कर सकते हैं। यह आपको एक ज़िप फ़ाइल बनाने और लिखने के लिए आईओ धाराओं का उपयोग करने के लिए उकसाएगा। प्लस StringIO के उपयोग में फेंक और आप एक स्ट्रिंग से यह कर सकते हैं:

# load a zip file from a URL into a string 
    resp = Net::HTTP.new("www.somewhere.com", 80).get("/some.zip") 
    zip_as_string = response.body 

    # open as a zip 
    zip = Zip::ZipCentralDirectory.read_from_stream(StringIO.new(zip_as_string)) 

    # work with the zip file. 
    # i just output the names of each entry to show that it was read correctly 
    zip.each { |zf| puts zf.name } 

    # write zip back to an output stream 
    out = StringIO.new 
    zip.write_to_stream(out) 

    # use 'out' or 'out.string' to do whatever with the resulting zip file. 
    out.string 

अद्यतन:

यह वास्तव में सब पर काम नहीं करता। यह एक पठनीय ज़िप फ़ाइल लिख देगा, लेकिन केवल ज़िप फ़ाइल की 'सामग्री की तालिका'। सभी आंतरिक फाइलें 0 लंबाई हैं। ज़िप कार्यान्वयन में आगे बढ़ना, ऐसा लगता है कि यह केवल स्मृति में ज़िप प्रविष्टि 'मेटाडाटा' रखता है, और यह सब कुछ पढ़ने के लिए अंतर्निहित फ़ाइल पर वापस जाता है। इस पर आधारित, ऐसा लगता है कि फाइल सिस्टम को लिखने के बिना ज़िप कार्यान्वयन का उपयोग करना असंभव है।

4

एक ही मुद्दा था, यह फ़ाइल को बंद करने और डाटा पढ़ने और यह रूप में send_data

फिर एक और पुस्तकालय कि Heroku पर ठीक काम करता है और इन-स्मृति बफ़र्स के साथ संभाल कर सकते हैं पाया स्ट्रीमिंग द्वारा काम पाने के लिए मिल गया है: यह zipruby है (rubyzip नहीं)।

buffer = '' 
Zip::Archive.open_buffer(buffer, Zip::CREATE) do |archive| 
    files.each do |wood, report| 
    title = wood.abbreviation+".txt" 
    archive.add_buffer(title, report); 
    end 
end 
file_name = "dimter_#{@offer.customerName}_#{Time.now.strftime("%m%d%Y_%H%M")}.zip" 
send_data buffer, :type => 'application/zip', :disposition => 'attachment', :filename => file_name 
संबंधित मुद्दे