HTTPClient रिस्पांस से GZip स्ट्रीम को डिकम्प्रेस करना


93

मैं एक एपीआई से जुड़ने की कोशिश कर रहा हूं, जो कि GZip रिटर्न JSON को WCF सेवा (WCF सेवा से WCF सेवा) तक एन्कोडेड करता है। मैं API से कनेक्ट करने के लिए HTTPClient का उपयोग कर रहा हूं और JSON ऑब्जेक्ट को एक स्ट्रिंग के रूप में वापस करने में सक्षम हूं । हालाँकि मुझे डेटाबेस में इस लौटे डेटा को स्टोर करने में सक्षम होने की आवश्यकता है और जैसे मैंने सोचा कि सबसे अच्छा तरीका होगा कि आप JSON ऑब्जेक्ट को किसी सरणी या बाइट या उन रेखाओं के साथ स्टोर कर सकें।

मैं विशेष रूप से GZip एन्कोडिंग की डिकम्प्रेसिंग से परेशान हूं और कई अलग-अलग उदाहरणों की कोशिश कर रहा हूं, लेकिन फिर भी यह नहीं मिल सकता है।

नीचे दिया गया कोड है कि मैं अपना कनेक्शन कैसे स्थापित कर रहा हूं और प्रतिक्रिया प्राप्त कर रहा हूं, यह वह कोड है जो एपीआई से एक स्ट्रिंग लौटाता है।

public string getData(string foo)
{
    string url = "";
    HttpClient client = new HttpClient();
    HttpResponseMessage response;
    string responseJsonContent;
    try
    {
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        response = client.GetAsync(url + foo).Result;
        responseJsonContent = response.Content.ReadAsStringAsync().Result;
        return responseJsonContent;
    }
    catch (Exception ex)
    {
        System.Windows.Forms.MessageBox.Show(ex.Message);
        return "";
    }
}

मैं इन StackExchange API , MSDN , और स्टेवओवरफ़्लो पर एक जोड़े जैसे कुछ अलग-अलग उदाहरणों का पालन कर रहा हूं , लेकिन मुझे इनमें से कोई भी काम करने में सक्षम नहीं किया गया है।

इसे पूरा करने का सबसे अच्छा तरीका क्या है, क्या मैं सही रास्ते पर हूं?

धन्यवाद दोस्तों।


"एक सरणी या बाइट में JSON ऑब्जेक्ट को वापस करने और संग्रहीत करने का सबसे अच्छा तरीका होगा" ध्यान दें कि एक स्ट्रिंग बाइट्स की एक सरणी है।
user3285954

जवाबों:


232

बस इस तरह HttpClient को पलटें:

HttpClientHandler handler = new HttpClientHandler()
{
    AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
};

using (var client = new HttpClient(handler))
{
    // your code
}

19 जून, 2020 को अपडेट करें: httpclient को 'ब्लॉक' का उपयोग करके ब्लॉक करने की सलाह नहीं दी जाती क्योंकि इससे पोर्ट थकावट हो सकती है।

private static HttpClient client = null;

ContructorMethod()
{
   if(client == null)
   {
        HttpClientHandler handler = new HttpClientHandler()
        {
            AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
        };        
        client = new HttpClient(handler);
   }
// your code            
 }

यदि .Net Core 2.1+ का उपयोग किया जाता है, तो IHttpClientFactory का उपयोग करने और अपने स्टार्टअप कोड में इस तरह का इंजेक्शन लगाने पर विचार करें।

 var timeout = Policy.TimeoutAsync<HttpResponseMessage>(
            TimeSpan.FromSeconds(60));

 services.AddHttpClient<XApiClient>().ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
        {
            AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
        }).AddPolicyHandler(request => timeout);

यदि मैं इस संरचना का उपयोग करता हूं, तो मैं httpClient से अपनी प्रतिक्रिया की सामग्री कैसे प्राप्त करूं? मैं c # के लिए सुपर नया हूं और मुझे नहीं लगता कि मैं यह कर रहा हूं।
FoxDeploy

1
जब आप इस समाधान का उपयोग करते हैं तो सामग्री प्राप्त करने के लिए कोड के लिए किसी परिवर्तन की आवश्यकता नहीं है। संदर्भ के लिए यहां देखें: stackoverflow.com/questions/26597665/…
DIG

1
भले ही यह एक पुरानी पोस्ट है, लेकिन इस जवाब ने मेरी समस्या को हल कर दिया है .netcore, 1.1 से 2.0 तक चल रहा है, ऐसा लगता है कि ग्राहक स्वचालित रूप से डिकम्प्रेसन कर रहा था, इसलिए मुझे इसे काम करने के लिए 2.0 में इस कोड को जोड़ना पड़ा ... धन्यवाद !
सेबेस्टियन कैस्टल्डी

3
बस @SebastianCastaldi पर वापस पिग्गी करने के लिए, लेकिन .net कोर 1.1 में ऑटोमैडकंपेशन सेट था, लेकिन .net कोर 2.0 में यह NONE पर सेट है। इसने मुझे यह पता लगाने के लिए बहुत लंबा रास्ता तय किया ...
KallDrexx

5
नोट: HttpClientअंदर इस्तेमाल नहीं किया जाना चाहिएusing
imba-tjd

1

मैंने नीचे दिए गए लिंक से डिकम्प्रेस GZip स्ट्रीम के लिए कोड का उपयोग किया। फिर आवश्यक JSON ऑब्जेक्ट को प्राप्त करने के लिए विघटित बाइट सरणी का उपयोग किया। आशा है कि यह कुछ मदद कर सकता है।

var readTask = result.Content.ReadAsByteArrayAsync().Result;
var decompressedData = Decompress(readTask);
string jsonString = System.Text.Encoding.UTF8.GetString(decompressedData, 0, decompressedData.Length);
ResponseObjectClass responseObject = Newtonsoft.Json.JsonConvert.DeserializeObject<ResponseObjectClass>(jsonString);

https://www.dotnetperls.com/decompress

static byte[] Decompress(byte[] gzip)
{
    using (GZipStream stream = new GZipStream(new MemoryStream(gzip), CompressionMode.Decompress))
    {
        const int size = 4096;
        byte[] buffer = new byte[size];
        using (MemoryStream memory = new MemoryStream())
        {
            int count = 0;
            do
            {
                count = stream.Read(buffer, 0, size);
                if (count > 0)
                {
                    memory.Write(buffer, 0, count);
                }
            }
            while (count > 0);
            return memory.ToArray();
        }
    }
}

0

ठीक है, इसलिए मैंने अंततः अपनी समस्या हल कर ली। अगर बेहतर तरीके हैं तो कृपया मुझे बताएं :-)

        public DataSet getData(string strFoo)
    {
        string url = "foo";

        HttpClient client = new HttpClient();
        HttpResponseMessage response;   
        DataSet dsTable = new DataSet();
        try
        {
               //Gets the headers that should be sent with each request
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
              //Returned JSON
            response = client.GetAsync(url).Result;
              //converts JSON to string
            string responseJSONContent = response.Content.ReadAsStringAsync().Result;
              //deserializes string to list
            var jsonList = DeSerializeJsonString(responseJSONContent);
              //converts list to dataset. Bad name I know.
            dsTable = Foo_ConnectAPI.ExtentsionHelpers.ToDataSet<RootObject>(jsonList);
              //Returns the dataset                
            return dsTable;
        }
        catch (Exception ex)
        {
            System.Windows.Forms.MessageBox.Show(ex.Message);
            return null;
        }
    }

       //deserializes the string to a list. Utilizes JSON.net. RootObject is a class that contains the get and set for the JSON elements

    public List<RootObject> DeSerializeJsonString(string jsonString)
    {
          //Initialized the List
        List<RootObject> list = new List<RootObject>();
          //json.net deserializes string
        list = (List<RootObject>)JsonConvert.DeserializeObject<List<RootObject>>(jsonString);

        return list;
    }

रूटऑब्जेक्ट में गेट सेट होता है जिसमें JSON का मान मिलेगा।

public class RootObject
{  
      //These string will be set to the elements within the JSON. Each one is directly mapped to the JSON elements.
      //This only takes into account a JSON that doesn't contain nested arrays
    public string EntityID { get; set; }

    public string Address1 { get; set; }

    public string Address2 { get; set; }

    public string Address3 { get; set; }

}

उपरोक्त वर्ग (तों) बनाने का सबसे आसान तरीका json2charp का उपयोग करना है जो इसे तदनुसार प्रारूपित करेगा और सही डेटापेट भी प्रदान करेगा।

निम्नलिखित Stackoverflow पर एक और जवाब से है यह फिर से नेस्टेड JSON को ध्यान में नहीं रखता है।

    internal static class ExtentsionHelpers
{
    public static DataSet ToDataSet<T>(this List<RootObject> list)
    {
        try
        {
            Type elementType = typeof(RootObject);
            DataSet ds = new DataSet();
            DataTable t = new DataTable();
            ds.Tables.Add(t);

            try
            {
                //add a column to table for each public property on T
                foreach (var propInfo in elementType.GetProperties())
                {
                    try
                    {
                        Type ColType = Nullable.GetUnderlyingType(propInfo.PropertyType) ?? propInfo.PropertyType;

                            t.Columns.Add(propInfo.Name, ColType);

                    }
                    catch (Exception ex)
                    {
                        System.Windows.Forms.MessageBox.Show(ex.Message);
                    }

                }
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message);
            }

            try
            {
                //go through each property on T and add each value to the table
                foreach (RootObject item in list)
                {
                    DataRow row = t.NewRow();

                    foreach (var propInfo in elementType.GetProperties())
                    {
                        row[propInfo.Name] = propInfo.GetValue(item, null) ?? DBNull.Value;
                    }

                    t.Rows.Add(row);
                }
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message);
            }

            insert.insertCategories(t);
            return ds.
        }
        catch (Exception ex)
        {
            System.Windows.Forms.MessageBox.Show(ex.Message);

            return null;
        }
    }
};

फिर अंत में उपर्युक्त डाटासेट को स्तंभों के साथ एक तालिका में सम्मिलित करना है जो JSON मैं मैप किए गए थे SQL SQL कॉपी और निम्न वर्ग

public class insert
{ 
    public static string insertCategories(DataTable table)
    {     
        SqlConnection objConnection = new SqlConnection();
          //As specified in the App.config/web.config file
        objConnection.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["foo"].ToString();

        try
        {                                 
            objConnection.Open();
            var bulkCopy = new SqlBulkCopy(objConnection.ConnectionString);

            bulkCopy.DestinationTableName = "dbo.foo";
            bulkCopy.BulkCopyTimeout = 600;
            bulkCopy.WriteToServer(table);

            return "";
        }
        catch (Exception ex)
        {
            System.Windows.Forms.MessageBox.Show(ex.Message);
            return "";
        }
        finally
        {
            objConnection.Close();
        }         
    }
};

तो ऊपर एक वेबएपीआई से JSON को एक डेटाबेस में सम्मिलित करने के लिए काम करता है। यह कुछ ऐसा है जो मुझे काम करने के लिए मिलता है। लेकिन किसी भी तरह से मुझे उम्मीद नहीं है कि यह सही होगा। यदि आपके पास कोई सुधार है तो कृपया उसके अनुसार अपडेट करें।


2
आपको अंतर्निहित धाराओं के उचित, समय पर निपटान और समापन सुनिश्चित करने के लिए प्रत्येक HttpClientऔर अपने HttpResponseअंदर एक using()बयान बनाना चाहिए ।
इयान मर्सर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.