2012-11-09 21 views
9

से अपलोड प्रगति की रिपोर्ट करना मैं एक छोटा node.js एप्लिकेशन लिख रहा हूं जो HTML फॉर्म से मल्टीपार्ट पोस्ट प्राप्त करता है और आने वाले डेटा को अमेज़ॅन S3 पर पाइप करता है। formidable मॉड्यूल multipart parsing प्रदान करता है, प्रत्येक भाग को नोड Stream के रूप में उजागर करता है। knox मॉड्यूल PUT को S3 को संभालता है।node.js

var form = new formidable.IncomingForm() 
, s3 = knox.createClient(conf); 

form.onPart = function(part) { 
    var put = s3.putStream(part, filename, headers, handleResponse); 
    put.on('progress', handleProgress); 
}; 

form.parse(req); 

मैं socket.io के माध्यम से ब्राउज़र ग्राहक के लिए अपलोड प्रगति रिपोर्ट कर रहा हूं, लेकिन कठिनाई हो रही है इन नंबरों S3 अपलोड करने के लिए नोड के वास्तविक प्रगति को प्रतिबिंबित करने के चल रहा है।

जब ब्राउजर नोड अपलोड करने के लिए तत्काल निकट होता है, क्योंकि यह तब होता है जब स्थानीय नेटवर्क पर नोड प्रक्रिया चल रही है, प्रगति सूचक तुरंत 100% तक पहुंचता है। अगर फ़ाइल बड़ी है, यानी 300 एमबी, प्रगति संकेतक धीरे-धीरे बढ़ता है, लेकिन हमारे अपस्ट्रीम बैंडविड्थ की तुलना में अभी भी तेज है। 100% प्रगति पर हमला करने के बाद, क्लाइंट तब लटकता है, संभवतः एस 3 अपलोड को समाप्त करने के लिए प्रतीक्षा कर रहा है।

मुझे पता है putStream आंतरिक रूप से नोड की stream.pipe विधि का उपयोग करता है, लेकिन मुझे यह समझ में नहीं आता कि यह वास्तव में कैसे काम करता है। मेरी धारणा यह है कि नोड आने वाले डेटा को जितनी जल्दी हो सके उतना तेज़ कर देता है, इसे स्मृति में फेंक देता है। यदि लेखन धारा डेटा को तेज़ी से ले जा सकती है, तो एक बार में स्मृति में थोड़ा डेटा रखा जाता है, क्योंकि इसे लिखा और त्याग दिया जा सकता है। यदि लिखने की धारा धीमी है, यद्यपि यह यहां है, तो संभवतः हमें उस आने वाले डेटा को मेमोरी में तब तक रखना होगा जब तक इसे लिखा जा सके। चूंकि हम प्रगति को उत्सर्जित करने के लिए रीड स्ट्रीम पर data ईवेंट सुन रहे हैं, इसलिए हम अपलोड की रिपोर्टिंग को समाप्त करते हैं क्योंकि यह वास्तव में तेज़ी से चल रहा है।

क्या इस समस्या की मेरी पहचान कहीं भी निशान के करीब है? मैं इसे ठीक करने के बारे में कैसे जा सकता हूं? क्या मुझे write, drain और pause के साथ नीचे उतरने और गंदे होने की आवश्यकता है?

+0

आप 'handleProgress' कॉलबैक अंदर वापस ब्राउज़र को प्रगति रिपोर्ट कर रहे हैं? आपने _any_ कोड पोस्ट नहीं किया है जिसके वास्तविक प्रगति रिपोर्टिंग के साथ कुछ भी हो सकता है। अधिक कोड पोस्ट करने में मदद की संभावना है। – lanzz

+0

आप जिस नोड.जेएस का उपयोग कर रहे हैं उसका संस्करण क्या है? अपरिवर्तनीय [वहाँ एक बग था] (https://groups.google.com/forum/?fromgroups=#!topic/nodejs/pzhtOO6ePZ0) 'request.pause()' (आपके मामले में: 'part' चर) के साथ नोड.जेएस v0.6.x, जिसे आंतरिक रूप से '.pipe()' द्वारा उपयोग किया जाता है। यह v0.7 + में तय किया जाना चाहिए। – freakish

+0

@lanzz - यह सही है। वास्तविक कार्यान्वयन वास्तव में प्रासंगिक नहीं है हालांकि: प्रश्न के प्रयोजनों के लिए यह 'console.log'' भी हो सकता है। – cantlin

उत्तर

7

आपकी समस्या यह है कि stream.pause isn't implemented on the part, जो मल्टीपार्ट फॉर्म पार्सर से आउटपुट का एक बहुत ही सरल रीडस्ट्रीम है।

Knox instructs the s3 request to emit "progress" events whenever the part emits "data"। हालांकि part धारा विराम को अनदेखा करती है, इसलिए प्रगति की घटनाओं को जितना तेज़ किया जाता है उतना तेज़ रूप से फॉर्म डेटा अपलोड और पार्स किया जाता है।

दुर्जेय form, हालांकि, पता है कि कैसे करने के लिए दोनों pause और resume (यह अनुरोध यह पार्स करने है के लिए कॉल प्रॉक्सी)।

कुछ इस तरह आपकी समस्या का समाधान करना चाहिए:

form.onPart = function(part) { 

    // once pause is implemented, the part will be able to throttle the speed 
    // of the incoming request 
    part.pause = function() { 
     form.pause(); 
    }; 

    // resume is the counterpart to pause, and will fire after the `put` emits 
    // "drain", letting us know that it's ok to start emitting "data" again 
    part.resume = function() { 
     form.resume(); 
    }; 

    var put = s3.putStream(part, filename, headers, handleResponse); 
    put.on('progress', handleProgress); 
}; 
+0

धन्यवाद @ संख्या1311407, महान जवाब। मैं पूछने के लिए बाध्य हूं: क्या आप इस तरह से 'रोकें' और 'फिर से शुरू' करने के लिए कोई महत्वपूर्ण कमी देख सकते हैं? असल में मुझे लगता है कि यह हमारे सर्वर को केवल एस 3 के रूप में उत्तरदायी बनाता है। मैंने इसे टेस्ट कोड [यहां] (https://github.com/cantlin/node-s3-proxy) में कार्यान्वित किया है। – cantlin

+0

जैसा कि मैं स्वयं नहीं हूं I/O, मैं वही बात सोचता हूं। लेकिन [node.js स्ट्रीम दस्तावेज़ पृष्ठ] (http://nodejs.org/api/http.html#http_request_pause) 'रोक' के लिए उपयोगी केस के रूप में अपलोड थ्रॉटलिंग का उल्लेख करता है। [अनुरोध के बारे में यह समाचार समूह चर्चा। "बग"] (https://groups.google.com/forum/#!msg/nodejs/yv6Dl-O-wYk/qPAKqKDDT9gJ) मूल्यवान (माइकल और मार्को की टिप्पणियां) के लायक है। – numbers1311407

+0

अंत में यह आपके लिए दो समस्याएं हल करता है: 1.) यह वास्तविक अपलोड पूरा होने तक क्लाइंट को लाइन पर रखता है, और 2.) यह सर्वर पर संभावित रूप से बड़ी मात्रा में डेटा बफर किए बिना ऐसा करने की अनुमति देता है। एस 3 अनुरोध से पहले एक बफर स्ट्रीम में पाइपिंग करके, प्रगति की निगरानी करने और अपलोड समाप्त होने पर क्लाइंट को वापस कॉल करके आप इस समस्या को हल कर सकते हैं। लेकिन यह # 2 बाहर फेंकता है। – numbers1311407