2015-02-26 14 views
5

पर AcceptEncoding संपीड़न सेट करें हम अपने क्लाइंट में उपयोगकर्ता-निर्धारित (सेटिंग्स स्क्रीन पर) वैकल्पिक gzip संपीड़न को लागू करने की कोशिश कर रहे हैं जो HttpClient का उपयोग करता है, इसलिए हम लॉग ऑन और कई अलग-अलग कॉलों पर प्रदर्शन की तुलना कर सकते हैं समय की अवधि। हमारा पहला प्रयास के रूप में इस बस सशर्त हैडर जोड़ने के लिए किया गया था:एचटीपी क्लाइंट: सशर्त रूप से सेटटाइम

HttpRequestMessage request = new HttpRequestMessage(Method, Uri); 
if (AcceptGzipEncoding) 
{ 
    _client.DefaultRequestHeaders.AcceptEncoding.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("gzip")); 
} 

//Send to the server 
result = await _client.SendAsync(request); 

//Read the content of the result response from the server 
content = await result.Content.ReadAsStringAsync(); 

यह सही अनुरोध बनाया है, लेकिन Gzipped प्रतिक्रिया वापसी पर decompressed नहीं किया गया था, एक विकृत प्रतिक्रिया में जिसके परिणामस्वरूप। मैंने पाया है कि हम HttpClientHandler शामिल करने के लिए जब HttpClient निर्माण किया था:

HttpClient _client = new HttpClient(new HttpClientHandler 
    { 
     AutomaticDecompression = DecompressionMethods.GZip 
    }); 

यह सब अच्छी तरह से काम करता है, लेकिन हम ग्राहक क्रम पर Accept-Encoding: gzip हैडर भेजता है या नहीं बदलना चाहते हैं, और वहाँ नहीं है HttpClient कन्स्ट्रक्टर को पास करने के बाद HttpClientHandler तक पहुंचने या बदलने का कोई तरीका दिखाई देता है। इसके अलावा, HttpRequestMessage ऑब्जेक्ट के हेडर को बदलने से अनुरोध के शीर्षकों पर कोई प्रभाव नहीं पड़ता है यदि उन्हें HttpClientHandler द्वारा परिभाषित किया गया है।

क्या यह परिवर्तन हर बार HttpClient पुनर्निर्माण किए बिना ऐसा करने का कोई तरीका है?

संपादित करें: मैं भी HttpClientHandler के लिए एक संदर्भ को संशोधित करने के क्रम में AutomaticDecompression बदलने की कोशिश की है, लेकिन है कि इस अपवाद फेंक रहा है:

इस उदाहरण पहले से ही एक या अधिक अनुरोध शुरू कर दिया है। पहले अनुरोध भेजने से पहले गुणों को केवल संशोधित किया जा सकता है।

+0

बस उत्सुक है, अब आप देखा है कि कैसे काम स्वत: विसंपीड़न है, क्यों * * ग्राहक प्रत्येक पुन: नहीं समय परिवर्तन बदल रहा है? यह वही है जो मैं यहां करता हूं, जब तक कि इसका कोई अच्छा कारण न हो। –

+0

@ToddMenier यह एक बहुत ही वैध सवाल है। यह कुछ ऐसा है जिसे हम विचार कर रहे हैं, लेकिन मुझे लगता है कि थोड़ा सा पुनर्गठन की आवश्यकता होगी, क्योंकि एक ही एचटीपी क्लाइंट कई क्षेत्रों में बंधे हैं। यह पहले के डेवलपर्स से विरासत में प्राप्त एक मामूली आकार का एप्लिकेशन है, इसलिए हमें केवल बदलावों को ध्यान से प्रबंधित करना होगा। हम इस सप्ताह इसे देख रहे होंगे।टिप्पणियों और मदद के लिए धन्यवाद। – pcdev

उत्तर

1

ऊपर टिप्पणियों के अनुसार, HttpClient पुनः वास्तव में केवल (मजबूत) तरीका यह है है। मैन्युअल डिकंप्रेशन हासिल किया जा सकता है लेकिन डीकोडिंग लागू करने के लिए यह निर्धारित करने के लिए सामग्री को एन्कोड किया गया है या नहीं, यह विश्वसनीय रूप से/कुशलता से निर्धारित करना बहुत मुश्किल लगता है।

7

आप लगभग पहले उदाहरण के साथ हैं, आपको केवल स्ट्रीम को डिफ्लेट करने की आवश्यकता है। एमएस के GZipSteam इस के साथ मदद मिलेगी:

HttpRequestMessage request = new HttpRequestMessage(Method, Uri); 
if (AcceptGzipEncoding) 
{ 
    _client.DefaultRequestHeaders.AcceptEncoding.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("gzip")); 
} 

//Send to the server 
result = await _client.SendAsync(request); 

//Read the content of the result response from the server 
using (Stream stream = await result.Content.ReadAsStreamAsync()) 
using (Stream decompressed = new GZipStream(stream, CompressionMode.Decompress)) 
using (StreamReader reader = new StreamReader(decompressed)) 
{ 
    content = reader.ReadToEnd(); 
} 
+1

हम्म, यह पता चला है कि यह उत्तर तब तक काम करता है जब तक कि सर्वर प्रतिक्रिया को gzip न करने का निर्णय लेता है (या कॉन्फ़िगर नहीं किया गया है), तो यह खत्म हो जाता है। दुर्भाग्य से HttpResponseMessage ऑब्जेक्ट से "सामग्री-एन्कोडिंग" शीर्षलेख प्राप्त करने का कोई आसान तरीका नहीं है [इस पोस्ट को देखें] (https://social.msdn.microsoft.com/Forums/windowsapps/en-US/cb7417b5-ca3e-44f6 -a272-9e2f8fc5d9b8/पोर्टेबल-httpclient-hides-contentlength-and-contentencoding-headers-with-gzip-encoding? forum = wpdevelop), तो ऐसा लगता है कि HttpClient को पुनर्निर्माण करना वास्तव में ऐसा करने का एकमात्र तरीका है। आपके इनपुट के लिए फिर से धन्यवाद। – pcdev

2

यदि आप एक ही HttpClient का उपयोग करना चाहते हैं और केवल कुछ अनुरोधों के लिए संपीड़न सक्षम करना चाहते हैं, तो आप स्वचालित डिकंप्रेशन का उपयोग करने में सक्षम नहीं हैं। जब स्वचालित डिकंप्रेशन सक्षम होता है, तो फ्रेमवर्क प्रतिक्रिया के शीर्षलेख Content-Encoding रीसेट करता है। इसका मतलब यह है कि आप यह पता लगाने में असमर्थ हैं कि प्रतिक्रिया वास्तव में संपीड़ित थी या नहीं। वैसे, Content-Length प्रतिक्रिया का शीर्षलेख डिकंप्रेस्ड सामग्री के आकार से मेल खाता है यदि आप स्वचालित डिकंप्रेशन चालू करते हैं।

तो आपको सामग्री को मैन्युअल रूप से डिक्रॉप करने की आवश्यकता है। निम्न नमूना gzip संकुचित सामग्री के लिए एक कार्यान्वयन से पता चलता है (जैसा भी में दिखाया गया है @ ToddMenier के response):

private async Task<string> ReadContentAsString(HttpResponseMessage response) 
{ 
    // Check whether response is compressed 
    if (response.Content.Headers.ContentEncoding.Any(x => x == "gzip")) 
    { 
     // Decompress manually 
     using (var s = await response.Content.ReadAsStreamAsync()) 
     { 
      using (var decompressed = new GZipStream(s, CompressionMode.Decompress)) 
      { 
       using (var rdr As New IO.StreamReader(decompressed)) 
       { 
        return await rdr.ReadToEndAsync(); 
       } 
      } 
     } 
    else 
     // Use standard implementation if not compressed 
     return await response.Content.ReadAsStringAsync(); 
} 
संबंधित मुद्दे