ASP.NET Core 6.0 API GZip压缩响应解压时出现不支持压缩方法错误
问题根源
服务端的CompressString方法存在致命错误:将GZip压缩生成的二进制字节数组直接通过Encoding.UTF8.GetString(compressedData)转换为字符串。压缩后的字节流并非合法的UTF-8字符序列,这种转换会破坏原始二进制数据,导致客户端接收到的是损坏的压缩数据,解压时自然抛出不支持的压缩方法异常。
修复方案
方案一:直接返回二进制压缩数据(推荐)
这是HTTP传输压缩内容的标准做法,避免字符串转换带来的数据损坏。
修改服务端代码
[HttpPost("[action]", Name = "GetData")] public IActionResult GetData(string request) { string data = GetStaticXMLFileData(); byte[] compressedData = CompressString(data); // 返回二进制压缩数据,指定正确的媒体类型与压缩标识 Response.Headers.Add("Content-Encoding", "gzip"); return File(compressedData, "text/xml"); } private byte[] CompressString(string text) { using (var memoryStream = new MemoryStream()) { using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Compress, true)) { using (var writer = new StreamWriter(gZipStream, Encoding.UTF8)) { writer.Write(text); } } return memoryStream.ToArray(); } }
修改客户端代码
private string GetDataAPIResponse() { string httpResponse = string.Empty; var urlValue = "https://localhost:44314/api/CompressedData/GetData?compress=true&result_format=xml"; var requestUri = new Uri(urlValue); var buffer = Encoding.UTF8.GetBytes("<data>Test</data>"); var byteContent = new ByteArrayContent(buffer); using (var httpClient = new HttpClient()) { // 告知服务端客户端支持gzip压缩 httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip")); using (var response = httpClient.PostAsync(requestUri, byteContent).GetAwaiter().GetResult()) { response.EnsureSuccessStatusCode(); using (var responseStream = response.Content.ReadAsStreamAsync().GetAwaiter().GetResult()) { Stream decompressStream = response.Content.Headers.ContentEncoding.Contains("gzip") ? new GZipStream(responseStream, CompressionMode.Decompress) : responseStream; using (var readStream = new StreamReader(decompressStream, Encoding.UTF8)) { httpResponse = readStream.ReadToEnd(); } } } return httpResponse; } }
方案二:Base64编码传输(仅当必须用字符串传输时)
如果业务限制必须返回字符串格式,可通过Base64编码确保二进制压缩数据安全传输,代价是传输体积增加约33%。
修改服务端代码
[HttpPost("[action]", Name = "GetData")] public IActionResult GetData(string request) { string data = GetStaticXMLFileData(); string compressedBase64 = CompressStringToBase64(data); return new ContentResult { Content = compressedBase64, ContentType = "text/plain", StatusCode = (int)HttpStatusCode.OK }; } private string CompressStringToBase64(string text) { using (var memoryStream = new MemoryStream()) { using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Compress, true)) { using (var writer = new StreamWriter(gZipStream, Encoding.UTF8)) { writer.Write(text); } } byte[] compressedData = memoryStream.ToArray(); return Convert.ToBase64String(compressedData); } }
修改客户端代码
private string GetDataAPIResponse() { string httpResponse = string.Empty; var urlValue = "https://localhost:44314/api/CompressedData/GetData?compress=true&result_format=xml"; var requestUri = new Uri(urlValue); var buffer = Encoding.UTF8.GetBytes("<data>Test</data>"); var byteContent = new ByteArrayContent(buffer); using (var httpClient = new HttpClient()) { using (var response = httpClient.PostAsync(requestUri, byteContent).GetAwaiter().GetResult()) { response.EnsureSuccessStatusCode(); string base64Content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult(); byte[] compressedData = Convert.FromBase64String(base64Content); using (var memoryStream = new MemoryStream(compressedData)) using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Decompress)) using (var readStream = new StreamReader(gZipStream, Encoding.UTF8)) { httpResponse = readStream.ReadToEnd(); } } return httpResponse; } }
内容的提问来源于stack exchange,提问作者Creative Learner
相关产品推荐
相关产品推荐

