2012-06-20 17 views
15

मैं Google क्रोम, सफारी और फ़ायरफ़ॉक्स में XMLHttpRequest का उपयोग कर एक JSON फ़ाइल लोड कर रहा हूं। सभी तीन ब्राउज़रों में मुझे ProgressEvent एस प्राप्त हो रहा है जो .loaded संपत्ति को सही ढंग से दिखाता है। हालांकि .lengthComputable संपत्ति गलत है और .total संपत्ति शून्य है। मैंने जांच की है कि Content-Length HTTP शीर्षलेख भेजा जा रहा है और यह सही है - यह है। प्रतिक्रिया gzip-encoded जा रही है, लेकिन Content-length सही ढंग से एन्कोडेड लंबाई (डिकंप्रेशन से पहले) दिखाता है।ProgressEvent.lengthComputable झूठी क्यों है?

मेरी लंबाई ProgressEvent एस में क्यों उपलब्ध नहीं होगी?

HTTP/1.1 200 OK 
ETag: "hKXdZA" 
Date: Wed, 20 Jun 2012 20:17:17 GMT 
Expires: Wed, 20 Jun 2012 20:17:17 GMT 
Cache-Control: private, max-age=3600 
X-AppEngine-Estimated-CPM-US-Dollars: $0.000108 
X-AppEngine-Resource-Usage: ms=2 cpu_ms=0 api_cpu_ms=0 
Content-Type: application/json 
Content-Encoding: gzip 
Server: Google Frontend 
Content-Length: 621606 

नोट::

यहाँ हेडर हैं फ़ाइल Google अनुप्रयोग इंजन के माध्यम से प्रस्तुत किया जा रहा है।

यहाँ जावास्क्रिप्ट है:

var req; 
if (window.XMLHttpRequest){ 
    req = new XMLHttpRequest(); 
    if(req.overrideMimeType){ 
     req.overrideMimeType("text/json"); 
    } 
}else{ 
    req = new ActiveXObject('Microsoft.XMLHTTP'); 
} 

// Listen for progress events 
req.addEventListener("progress", function (event) { 
    console.log(event, event.lengthComputable, event.total); 
    if (event.lengthComputable) { 
     self.progress = event.loaded/event.total; 
    } else if (this.explicitTotal) { 
     self.progress = Math.min(1, event.loaded/self.explicitTotal); 
    } else { 
     self.progress = 0; 
    } 
    self.dispatchEvent(Breel.Asset.ON_PROGRESS); 
}, false); 

req.open('GET', this.url); 

नोट: console.log कि कोड में तारीख करने के लिए .loaded रों के साथ घटनाओं के सैकड़ों दिखाया जा रहा है लेकिन .lengthComputable हमेशा गलत है और .total हमेशा शून्य है। self इस XMLHttpRequest के लिए ज़िम्मेदार वस्तु को संदर्भित करता है।

+1

क्या हम आपके पास जावास्क्रिप्ट कोड देख सकते हैं जो इस डेटा को देख रहा है? – tkone

+0

मैंने अभी जोड़ा है। –

+1

क्या आपने इसे गैर-Google ऐप इंजन सर्वर पर उपयोग करने का प्रयास किया है? यदि 'लंबाई कॉम्प्यूटेबल' xhr ऑब्जेक्ट से गलत है तो यह नहीं पता कि फ़ाइल कितनी देर तक है। हम यहां जीएई का उपयोग करते हैं और इसकी अधिकांश कार्यक्षमताओं के साथ बड़ी समस्याएं हैं - यह आश्चर्यजनक नहीं होगा। – tkone

उत्तर

14

यदि लंबाई कॉम्प्यूटेबल XMLHttpRequestProgressEvent के भीतर गलत है, तो इसका मतलब है कि सर्वर ने कभी भी प्रतिक्रिया में सामग्री-लंबाई शीर्षलेख नहीं भेजा है।

यदि आप प्रॉक्सी सर्वर के रूप में nginx का उपयोग कर रहे हैं, तो यह अपराधी हो सकता है, खासकर यदि यह प्रॉक्सी सर्वर के माध्यम से अपस्ट्रीम सर्वर से सामग्री-लंबाई शीर्षलेख को पास नहीं कर रहा है।

+0

यदि आप सामग्री-लंबाई वाले शीर्षलेख को अनदेखा कर रहे हैं, तो आपको बफर आकार भी सेट करना होगा आपके प्रतिक्रिया के बाइट्स को पकड़ने में सक्षम होने के लिए आपकी प्रतिक्रिया का। अन्यथा HTTP 1.1 में यह प्रतिक्रिया को वापस करने के लिए वापस आ जाएगा। –

+0

या, कई सालों बाद, क्रोम में gzip'd सामग्री का उपयोग करते समय, दाएं हेडर सेट होने पर भी। :-( – Arjan

1

उपयोग अपलोड

req.addEventListener के लिए req.upload.addEventListener event.lengthComputable हमेशा गलत

req.upload.addEventListener("progress", function (event) { 
    console.log(event, event.lengthComputable, event.total); 
    if (event.lengthComputable) { 
     self.progress = event.loaded/event.total; 
    } else if (this.explicitTotal) { 
     self.progress = Math.min(1, event.loaded/self.explicitTotal); 
    } else { 
     self.progress = 0; 
    } 
    self.dispatchEvent(Breel.Asset.ON_PROGRESS); 
}, false); 
+0

मैंने 'req.addEventListener'' event.lengthComputable' को भी सही देखा है। यह बड़े अनुरोधों के लिए झूठा प्रतीत होता है: मैंने जिस कोशिश की थी वह 10 एमबी जेपीजी था। मैंने व्यापक परीक्षण नहीं किया है, लेकिन मैंने व्यापक परीक्षण नहीं किया है, लेकिन आप सही हो सकते हैं कि 'req.upload' की' लंबाई कॉम्प्यूटेबल 'अधिक बार सच है। – trysis

+1

... लेकिन नाम की तरह सुझाव दिया गया है: यह ब्राउज़र से सर्वर पर अपलोड के लिए है, सर्वर से ब्राउज़र पर डाउनलोड के लिए नहीं। – Arjan

1

इस बीच 2017, बातें फ़ायरफ़ॉक्स में ठीक हैं होगा, लेकिन क्रोम नहीं है gzip'd सामग्री के लिए प्रगति दिखाएं।

ऐसा लगता है कि loaded और total संपीड़ित या असम्पीडित सामग्री का संदर्भ लें तो यह स्पष्ट रूप से स्पष्ट होने के कारण होता है। Since जून 26, 2014 the XMLHttpRequest specifications कर स्पष्ट किया कि वे प्रेषित (संपीड़ित) सामग्री का संदर्भ लेना चाहिए:

6,1। ProgressEvent इंटरफ़ेस का उपयोग कर फायरिंग की घटनाओं

[...] दिया प्रेषित और लंबाई [...],, एक घटना [...] ProgressEvent आग loaded विशेषता के लिए शुरू प्रेषित साथ और अगर लंबाईlengthComputable विशेषता 0 से शुरू नहीं हुई है और विशेषता लंबाई पर प्रारंभ की गई विशेषता है।

हालांकि 2015 क्रोमियम बग रिपोर्ट "XHR's progress events should handle gzipped content" बताते हैं कि चीजें अलग थे, और कहा गया है:

जब इनकोडिंग, total रहता 0 और lengthComputable होने की

घटना सेट नहीं है खुद को अभी भी निकाल दिया गया है, और event.loaded अभी भी आबादी है। लेकिन क्रोम फ्लाई पर gzip'd सामग्री को डिकंप्रेस कर रहा है और (आज) loaded को परिणामी डिकंप्रेस्ड लम्बाई पर सेट करता है, लंबाई संचरित नहीं करता है। इसकी तुलना Content-Length शीर्षलेख के मान से नहीं की जा सकती है, क्योंकि यह संकुचित सामग्री की लंबाई है, इसलिए loaded सामग्री की लंबाई से बड़ा हो जाएगा।

पर सबसे अच्छा एक कुछ संपीड़न कारक Content-Length के खिलाफ loaded तुलना करने के लिए मान सकता है, या सर्वर मूल लंबाई या सच संपीड़न कारक प्रदान करने के लिए कुछ कस्टम शीर्षक जोड़ कर, क्रोम के ऑन-मक्खी विसंपीड़न परिवर्तन नहीं होगा यह सोचते हैं।

मुझे नहीं पता कि क्रोम Content-Encoding के लिए अन्य मानों के लिए क्या करता है।

+0

कम से कम: मुझे लगता है कि 'event.loaded' का मान डिकंप्रेस्ड आकार (प्रेषित लंबाई की बजाय) होने का मान https: //crbug.com/763700 से संबंधित नहीं है ... – Arjan