XMLHttpRequest से प्रगति कैसे प्राप्त करें


133

क्या XMLHttpRequest (बाइट्स अपलोड, बाइट्स डाउनलोड) की प्रगति प्राप्त करना संभव है?

जब उपयोगकर्ता एक बड़ी फ़ाइल अपलोड कर रहा हो तो प्रगति पट्टी दिखाना उपयोगी होगा। मानक API इसका समर्थन नहीं करता है, लेकिन हो सकता है कि वहाँ के किसी भी ब्राउज़र में कुछ गैर-मानक एक्सटेंशन हो? यह एक बहुत स्पष्ट सुविधा की तरह लगता है सब के बाद से, ग्राहक जानता है कि कितने बाइट्स अपलोड / डाउनलोड किए गए थे।

नोट: मैं "प्रगति के लिए सर्वर सर्वेक्षण" विकल्प से अवगत हूं (यह वही है जो मैं अभी कर रहा हूं)। इसके साथ मुख्य समस्या (जटिल सर्वर-साइड कोड के अलावा) यह है कि आमतौर पर, एक बड़ी फ़ाइल अपलोड करते समय, उपयोगकर्ता का कनेक्शन पूरी तरह से बंद हो जाता है, क्योंकि अधिकांश आईएसपी खराब अपस्ट्रीम प्रदान करते हैं। इसलिए अतिरिक्त अनुरोध करना उतना प्रतिक्रियात्मक नहीं है जितना कि मुझे उम्मीद थी। मैं उम्मीद कर रहा था कि इस जानकारी को प्राप्त करने के लिए एक रास्ता (शायद गैर-मानक) होगा, जो कि ब्राउज़र में हर समय होता है।

जवाबों:


137

अपलोड किए गए बाइट्स के लिए यह काफी आसान है। बस xhr.upload.onprogressघटना की निगरानी करें । ब्राउज़र को फ़ाइलों के आकार और अपलोड किए गए डेटा के आकार का पता है, इसलिए यह प्रगति की जानकारी प्रदान कर सकता है।

डाउनलोड किए गए बाइट्स के लिए (जब जानकारी प्राप्त हो रही है xhr.responseText), यह थोड़ा अधिक कठिन है, क्योंकि ब्राउज़र को नहीं पता है कि सर्वर अनुरोध में कितने बाइट भेजे जाएंगे। केवल एक चीज जिसे ब्राउज़र इस मामले में जानता है वह प्राप्त होने वाले बाइट्स का आकार है।

इसके लिए एक समाधान है, यह Content-Lengthसर्वर स्क्रिप्ट पर एक हेडर सेट करने के लिए पर्याप्त है , बाइट्स के कुल आकार को प्राप्त करने के लिए ब्राउज़र प्राप्त करने वाला है।

अधिक जानकारी के लिए https://developer.mozilla.org/en/Using_XMLHttpRequest पर जाएं

उदाहरण: मेरा सर्वर स्क्रिप्ट एक ज़िप फ़ाइल पढ़ता है (इसमें 5 सेकंड लगते हैं):

$filesize=filesize('test.zip');

header("Content-Length: " . $filesize); // set header length
// if the headers is not set then the evt.loaded will be 0
readfile('test.zip');
exit 0;

अब मैं सर्वर स्क्रिप्ट की डाउनलोड प्रक्रिया की निगरानी कर सकता हूं, क्योंकि मुझे पता है कि यह कुल लंबाई है:

function updateProgress(evt) 
{
   if (evt.lengthComputable) 
   {  // evt.loaded the bytes the browser received
      // evt.total the total bytes set by the header
      // jQuery UI progress bar to show the progress on screen
     var percentComplete = (evt.loaded / evt.total) * 100;  
     $('#progressbar').progressbar( "option", "value", percentComplete );
   } 
}   
function sendreq(evt) 
{  
    var req = new XMLHttpRequest(); 
    $('#progressbar').progressbar();    
    req.onprogress = updateProgress;
    req.open('GET', 'test.php', true);  
    req.onreadystatechange = function (aEvt) {  
        if (req.readyState == 4) 
        {  
             //run any callback here
        }  
    };  
    req.send(); 
}

29
वर्थ नोटिंग, "सामग्री-लंबाई" एक अनुमानित लंबाई नहीं है, इसकी सटीक लंबाई होनी चाहिए, बहुत छोटी और ब्राउज़र डाउनलोड को काट देगा, बहुत लंबा और ब्राउज़र मान लेगा कि डाउनलोड पूरा होने में विफल रहा है।
14:55 पर क्रिस चिलवर्स

@ChrisChilvers का मतलब है कि एक PHP फ़ाइल की सही गणना नहीं की जा सकती है, है ना?
हाइड्रोपर

1
उस उदाहरण में @nicematt यह ठीक है क्योंकि यह एक फ़ाइल से आता है, लेकिन यदि आप ज़िप को सीधे मेमोरी से स्ट्रीम कर रहे थे तो आप केवल एक सामग्री की लंबाई नहीं बना सकते थे या इसका अनुमान नहीं लगा सकते थे।
क्रिस चिल्वर्स

3
@ TheProHands जब आप एक .php पृष्ठ पर जाते हैं, तो सर्वर PHP फ़ाइल चलाता है और आपको इसका आउटपुट भेजता है । सर्वर को आउटपुट की लंबाई भेजनी चाहिए, न कि .php फ़ाइल।
लेवेज़

क्या कोई यह बता सकता है कि लाइन "$ ('# प्रोग्रेसबार') क्या है। उत्तरोत्तर (" विकल्प "," मूल्य ", प्रतिशत पूर्ण);" माध्यम? क्या यह एक विशिष्ट प्लग इन है? यह कैसे काम करता है? कृपया उत्तर को नए उपयोगकर्ताओं के लिए समझने योग्य बनाएं।
ज़ैक


8

सबसे आशाजनक दृष्टिकोण में से एक यह है कि हस्तांतरण का कितना पूरा हो गया है, यह पूछने के लिए एक दूसरा संचार चैनल सर्वर पर वापस खोला जा रहा है।


24
मुझे लगता है कि लिंक मृत हो सकता है
रोनी रोयस्टोन


5

अपलोड किए गए कुल के लिए ऐसा नहीं लगता कि इसे संभालना है, लेकिन डाउनलोड के लिए कुछ ऐसा ही है। एक बार रेडी 3 होने के बाद, आप समय-समय पर रिस्पॉन्स को क्वेरी कर सकते हैं, ताकि स्ट्रींग के रूप में अब तक डाउनलोड की गई सभी सामग्री प्राप्त हो सके (यह IE में काम नहीं करता है), जब तक यह सब उपलब्ध नहीं है, तब तक यह रेडीस्टेट 4 में परिवर्तित हो जाएगा। कुल किसी भी समय डाउनलोड किए गए बाइट्स रिस्पांस में संग्रहीत स्ट्रिंग में कुल बाइट्स के बराबर होंगे।

अपलोड प्रश्न के लिए सभी या कुछ भी नहीं के लिए, क्योंकि आपको अपलोड के लिए एक स्ट्रिंग पास करना होगा (और यह संभव है कि उस के कुल बाइट्स को निर्धारित करना) रेडीस्टेट 0 और 1 के लिए भेजा गया कुल बाइट 0 होगा, और रेडीस्टेट के लिए कुल। 2 आपके द्वारा पास किए गए स्ट्रिंग में कुल बाइट्स होगा। रेडी 3 और 4 में भेजे गए और प्राप्त किए गए कुल बाइट्स मूल स्ट्रिंग में बाइट्स का योग होगा और साथ ही रिस्पांस में कुल बाइट्स।


3

<!DOCTYPE html>
<html>
<body>
<p id="demo">result</p>
<button type="button" onclick="get_post_ajax();">Change Content</button>
<script type="text/javascript">
	function update_progress(e)
	{
	  if (e.lengthComputable)
	  {
	    var percentage = Math.round((e.loaded/e.total)*100);
	    console.log("percent " + percentage + '%' );
	  }
	  else 
	  {
	  	console.log("Unable to compute progress information since the total size is unknown");
	  }
	}
	function transfer_complete(e){console.log("The transfer is complete.");}
	function transfer_failed(e){console.log("An error occurred while transferring the file.");}
	function transfer_canceled(e){console.log("The transfer has been canceled by the user.");}
	function get_post_ajax()
	{
	  	var xhttp;
	  	if (window.XMLHttpRequest){xhttp = new XMLHttpRequest();}//code for modern browsers} 
	 	else{xhttp = new ActiveXObject("Microsoft.XMLHTTP");}// code for IE6, IE5	  	
	  	xhttp.onprogress = update_progress;
		xhttp.addEventListener("load", transfer_complete, false);
		xhttp.addEventListener("error", transfer_failed, false);
		xhttp.addEventListener("abort", transfer_canceled, false);	  	
	  	xhttp.onreadystatechange = function()
	  	{
	    	if (xhttp.readyState == 4 && xhttp.status == 200)
	    	{
	      		document.getElementById("demo").innerHTML = xhttp.responseText;
	    	}
	  	};
	  xhttp.open("GET", "http://it-tu.com/ajax_test.php", true);
	  xhttp.send();
	}
</script>
</body>
</html>

परिणाम


2

यदि आपके पास अपाचे स्थापित करने और तीसरे पक्ष के कोड पर भरोसा करने के लिए उपयोग किया जाता है, तो आप अपाचे अपलोड प्रगति मॉड्यूल का उपयोग कर सकते हैं (यदि आप अपाचे का उपयोग करते हैं, तो एक नगनेक्स अपलोड प्रगति मॉड्यूल भी है )।

अन्यथा, आपको एक स्क्रिप्ट लिखनी होगी जो आप फ़ाइल की स्थिति (उदाहरण के लिए tmp फ़ाइल की फ़ाइलों की जाँच करना) का अनुरोध करने के लिए बैंड से बाहर निकल सकते हैं।

फ़ायरफ़ॉक्स 3 में कुछ काम चल रहा है। मेरा मानना ​​है कि ब्राउज़र में अपलोड प्रगति समर्थन को जोड़ना है, लेकिन यह सभी ब्राउज़रों में नहीं जा रहा है और थोड़ी देर के लिए व्यापक रूप से अपनाया जाएगा (अधिक दया है)।


-7

शुद्ध जावास्क्रिप्ट के साथ ऐसा करने का एकमात्र तरीका कुछ प्रकार के मतदान तंत्र को लागू करना है। सर्वर द्वारा प्राप्त बाइट्स की संख्या प्राप्त करने के लिए आपको निश्चित अंतराल (उदाहरण के लिए प्रत्येक 5 सेकंड) पर अजाक्स अनुरोध भेजने की आवश्यकता होगी।

फ्लैश का उपयोग करने के लिए एक अधिक कुशल तरीका होगा। फ्लेक्स घटक FileReference समय-समय पर पहले से अपलोड किए गए बाइट्स की संख्या को पकड़े हुए एक 'प्रगति' घटना को भेजता है। यदि आपको जावास्क्रिप्ट के साथ छड़ी करने की आवश्यकता है, तो एक्शनस्क्रिप्ट और जावास्क्रिप्ट के बीच पुल उपलब्ध हैं। अच्छी खबर यह है कि यह काम आपके लिए पहले ही किया जा चुका है :)

SWFUpload

यह लाइब्रेरी फ़्लैश प्रगति घटना पर एक जावास्क्रिप्ट हैंडलर को पंजीकृत करने की अनुमति देती है।

इस समाधान में सर्वर साइड पर एडिशननल रिसोर्स की आवश्यकता नहीं होने का बड़ा फायदा है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.