2015-03-12 5 views
6

मैं बड़े पेज (लगभग 1.5 जीबी आकार) डाउनलोड करने के लिए बाकी क्लाइंट का उपयोग कर रहा हूं। पुनर्प्राप्त मूल्य को फ़ाइल में सहेजने से स्मृति में संग्रहीत किया जाता है। नतीजतन मेरा प्रोग्राम failed to allocate memory (NoMemoryError) के साथ दुर्घटनाग्रस्त हो गया।आराम से क्लाइंट का उपयोग डिस्क पर फ़ाइल को बिना किसी स्मृति के लोड करने के लिए पहले

लेकिन इस डेटा को स्मृति में रखना आवश्यक नहीं है, यह सीधे डिस्क पर भी सहेजा जा सकता है।

मैंने पाया "आप कर सकते हैं: (...) मैन्युअल रूप से प्रतिक्रिया को संभालने के लिए (उदाहरण के लिए इसे स्मृति में पढ़ने के बजाय इसे स्ट्रीम के रूप में संचालित करने के लिए) अधिक जानकारी के लिए RestClient :: अनुरोध के दस्तावेज़ देखें।" https://github.com/rest-client/rest-client दुर्भाग्यवश http://www.rubydoc.info/gems/rest-client/1.7.3/RestClient/Request पढ़ने के बाद मुझे नहीं पता कि यह कैसे पूरा किया जा सकता है।

मुझे यह भी पता है कि मैं अन्य लाइब्रेरी (Using WWW:Mechanize to download a file to disk without loading it all in memory first) का उपयोग कर सकता हूं लेकिन मेरा प्रोग्राम पहले से ही बाकी क्लाइंट का उपयोग कर रहा है।

सरलीकृत कोड:

data = RestClient::Request.execute(:method => :get, :url => url, :timeout => 3600) 
file = File.new(filename, 'w') 
file.write data 
file.close 

कोड - https://github.com/mkoniecz/CartoCSSHelper/blob/395deab626209bcdafd675c2d8e08d0e3dd0c7f9/downloader.rb#L126

+0

http://www.rubydoc.info/gems/rest-client/1.7.3/RestClient/Request#fetch_body-instance_method इस विधि के स्रोतों पढ़ सकते हैं और इस के लिए, लेकिन जैसे ख़ाली लागू डेटा सीधे डेटा में स्टोर करें। – iced

+0

आप बिल्टिन लाइब्रेरी ओपनुरि का उपयोग कर सकते हैं: 'आवश्यकता' ओपन-यूरी '; File.open (पथ, 'डब्ल्यू') {| एफ | IO.copy_stream (खुला (यूआरएल), एफ)} '। अगर फ़ाइल बड़ी 'ओपन' है तो इसे स्वचालित रूप से टेम्पम्फाइल पर लिखकर वापस कर दी जाएगी। अगर फ़ाइल काफी छोटी है तो यह इसे 'स्ट्रिंगियो' में लिख जाएगी। किसी भी तरह से आपके पास एक io ऑब्जेक्ट होगा जिसे आप वांछित स्थान पर ब्लॉक-कॉपी कर सकते हैं। –

+0

क्या आपने इसे RestClient से हल किया था? मुझे एक ही समस्या है लेकिन ओपन-यूरी का उपयोग नहीं कर सकता क्योंकि यह POST अनुरोधों का समर्थन नहीं करता है। – Raoot

उत्तर

1

raw_response का उपयोग करने का एक और तरीका है। यह आमतौर पर /tmp में फ़ाइल में सहेजता है। यह बिना किसी समस्या के रीडायरेक्ट को संभालता है। Streaming Responses देखें। यहाँ उनके उदाहरण है:

>> raw = RestClient::Request.execute(
      method: :get, 
      url: 'http://releases.ubuntu.com/16.04.2/ubuntu-16.04.2-desktop-amd64.iso', 
      raw_response: true) 
=> <RestClient::RawResponse @code=200, @file=#<Tempfile:/tmp/rest-client.20170522-5346-1pptjm1>, @request=<RestClient::Request @method="get", @url="http://releases.ubuntu.com/16.04.2/ubuntu-16.04.2-desktop-amd64.iso">> 
>> raw.file.size 
=> 1554186240 
>> raw.file.path 
=> "/tmp/rest-client.20170522-5346-1pptjm1" 
2

मेरे मूल जवाब RestClient::Request#execute करने के लिए एक ब्लॉक गुजर पदोन्नत लेकिन यह केवल ब्लॉक करने के लिए डेटा पारित कर दिया एक बार पूर्ण प्रतिक्रिया पढ़ा जाता है। इस प्रकार अभ्यास बेकार rendering। यह ठीक से ऐसा करने का तरीका है:

File.open('/tmp/foo.iso', 'w') {|f| 
    block = proc { |response| 
     response.read_body do |chunk| 
     puts "Working on response" 
     f.write chunk 
     end 
    } 
    RestClient::Request.new(method: :get, url: 'http://mirror.pnl.gov/releases/xenial/ubuntu-16.04-server-amd64.iso', block_response: block).execute 
} 

यह संबंधित rest-client project issue से है।

नोट: पुनर्निर्देशन इस मोड में काम नहीं करता है, साथ ही आप HTTP निकास स्थिति, कुकीज़, शीर्षलेख इत्यादि खो देते हैं। आशा है कि यह कुछ दिन तय किया जाएगा।

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

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