HTTP Client 응답으로부터의 GZip 스트림 압축 해제
WCF 서비스(WCF 서비스에서 WCF 서비스로)에서 GZip 인코딩된 JSON을 반환하는 api에 접속하려고 합니다.HTTP Client를 사용하여 API에 접속하고 있으며 JSON 오브젝트를 문자열로 반환할 수 있었습니다.그러나 이 반환된 데이터를 데이터베이스에 저장할 수 있어야 하므로 JSON 개체를 반환하여 해당 행에 따라 배열 또는 바이트에 저장하는 것이 가장 좋은 방법이라고 생각했습니다.
특히 GZIP 인코딩의 압축 해제에 문제가 있어 여러 가지 예를 시도했지만 아직 취득할 수 없습니다.
아래 코드는 제가 접속을 확립하고 응답을 받는 방법이며, API에서 문자열을 반환하는 코드입니다.
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, stackoverflow와 같은 몇 가지 다른 예를 따르고 있지만, 이 중 어느 것도 나에게 도움이 되지 않습니다.
내가 제대로 가고 있는 중인데, 어떻게 해야 할 가장 좋은 방법은 무엇일까요?
여러분 감사합니다.
Http Client를 다음과 같이 인스턴스화합니다.
HttpClientHandler handler = new HttpClientHandler()
{
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
};
using (var client = new HttpClient(handler)) //see update below
{
// your code
}
2020년 6월 19일 갱신: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+ 에서는, IHttp Client Factory 를 사용해, 스타트 업 코드에 이와 같이 삽입하는 것을 검토해 주세요.
var timeout = Policy.TimeoutAsync<HttpResponseMessage>(
TimeSpan.FromSeconds(60));
services.AddHttpClient<XApiClient>().ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
{
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
}).AddPolicyHandler(request => timeout);
아래 링크의 코드를 사용하여 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();
}
}
}
그래, 그래서 결국 내 문제를 해결했어.더 좋은 방법이 있으면 알려주세요:-)
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;
}
Root Object에는 JSON 값을 가져오는 get 세트가 포함되어 있습니다.
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를 사용하는 것입니다.json2charp는 그에 맞게 포맷하고 올바른 데이터 유형도 제공합니다.
다음으로 스택오버플로우 상의 다른 응답에 대한 예를 제시하겠습니다.이 응답에서는 중첩된 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 벌크복사 및 다음 클래스를 사용합니다.
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을 삽입하는 데 사용됩니다.API를 데이터베이스로 변환합니다.이건 내가 일을 시작하는 거야하지만 나는 결코 그것이 완벽하리라고 기대하지 않는다.개선 사항이 있으면 그에 따라 업데이트해 주십시오.
서버가 content-type이 br인 'Brotli'와 같은 다른 압축 스킴을 사용하는 경우 조만간 코드가 중단될 수 있습니다.
clientHandler를 사용하여 httpClient에서 압축을 푸는 비디오를 만들었습니다.
httpClientHandler에 의해 처리되는 압축알고
언급URL : https://stackoverflow.com/questions/20990601/decompressing-gzip-stream-from-httpclient-response
'programing' 카테고리의 다른 글
as 키워드는 어떤 역할을 합니까? (0) | 2023.02.28 |
---|---|
Java의 Mono 클래스: 무엇을 언제 사용할 수 있습니까? (0) | 2023.02.28 |
차트JS 꺽은선형 차트 - 선 아래 색 제거 (0) | 2023.02.28 |
웹 API 복합 매개 변수 속성이 모두 null입니다. (0) | 2023.02.28 |
타이프 스크립트에서 비동기 함수 유형을 정의하는 방법 (0) | 2023.02.28 |