System.IO.InvalidDataException:“存档条目是使用不受支持的压缩方法进行压缩的。”

问题描述 投票:0回答:1

我正在使用 ASP.NET Core 6.0。我有一个返回压缩数据的 API。我的代码的简化版本如下所示:

[HttpPost("[action]", Name = "GetData")]
public IActionResult GetData(string request)
{
     string data = GetStaticXMLFileData();
     data = CompressString(data);

     return new ContentResult
     {
         Content = data,
         ContentType = "text/xml",
         StatusCode = (int)HttpStatusCode.OK
     };
}

private string CompressString(string text)
{
    string compressedString;

    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();

            compressedString = System.Text.Encoding.UTF8.GetString(compressedData);
        }
    }

    return compressedString;
}

这个 API 端点运行良好,我已经从 Swagger 测试了它。

现在,我尝试在我的客户端代码中使用它们,如下所示:

private string GetDataAPIResponse()
{
    string httpResponse = string.Empty;

    var urlValue = string.Format("https://localhost:44314/api/CompressedData/GetData?compress=true&result_format=xml");
    var requestUri = new Uri(urlValue);

    var buffer = System.Text.Encoding.UTF8.GetBytes("<data>Test</data>"); //Sample Data Request
    var byteContent = new ByteArrayContent(buffer);

    using (var httpClient = new HttpClient())
    {
        using (var response = httpClient.PostAsync(requestUri, byteContent).GetAwaiter().GetResult())
        {
            response.EnsureSuccessStatusCode();

            if (response.IsSuccessStatusCode && response.StatusCode == HttpStatusCode.OK)
            {
                Task<Stream> task = response.Content.ReadAsStreamAsync();
                task.Wait();
                Stream responseStream = Constants.IsCompressed ?
                                        new GZipStream(task.Result, CompressionMode.Decompress) :
                                        task.Result;

                if (responseStream != null)
                {
                    using (var readStream = new StreamReader(responseStream, Encoding.UTF8))
                        httpResponse = readStream.ReadToEnd(); //Here, I got the Error.
                }
            }
        }

        return httpResponse;
    }
}

我无法使用此代码获得解压缩的响应。

在这行代码中,我收到错误:

httpResponse = readStream.ReadToEnd();

错误是:

System.IO.InvalidDataException:使用不支持的压缩方法压缩存档条目

堆栈跟踪:

在 System.IO.Compression.Inflater.Inflate(FlushCode 刷新代码)
在 System.IO.Compression.Inflater.ReadInflateOutput(Byte* bufPtr,Int32 长度,FlushCode flashCode,Int32& bytesRead)
在 System.IO.Compression.Inflater.ReadOutput(Byte* bufPtr, Int32 长度, Int32& bytesRead)
在System.IO.Compression.Inflater.InflateVerified(字节* bufPtr,Int32长度)
在 System.IO.Compression.DeflateStream.ReadCore(Span`1 缓冲区)
在 System.IO.Compression.DeflateStream.Read(Byte[] 缓冲区,Int32 偏移量,Int32 计数)
在 System.IO.Compression.GZipStream.Read(Byte[] 缓冲区,Int32 偏移量,Int32 计数)
在 System.IO.StreamReader.ReadBuffer()
在 System.IO.StreamReader.ReadToEnd()

有人可以建议我一个解决方案吗?

c# exception compression .net-6.0 asp.net-core-6.0
1个回答
0
投票

客户端和服务器代码都是完全错误的。您不应该将压缩文件重新编码回文本。只需将其作为字节或流传递

[HttpPost("[action]", Name = "GetData")]
public IActionResult GetData(string request)
{
     string data = GetStaticXMLFileData();
     var compressedStream = CompressString(data);
     return new FileStreamResult(compressedStream, "text/xml");
}

private Stream CompressString(string text)
{
    var memoryStream = new MemoryStream();
    using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Compress, true))
    using (var writer = new StreamWriter(gZipStream, Encoding.UTF8))
    {
        writer.Write(text);
    }

    memoryStream.Position = 0; // seek back to start
    return memoryStream;
}

客户不应该使用

.GetResult
.Wait
,只能使用
await

static HttpClient _httpClient = new HttpClient(); // use static or DI client to prevent socket exhaustion

private async Task<string> GetDataAPIResponse()
{
    var urlValue = $"https://localhost:44314/api/CompressedData/GetData?compress=true&result_format=xml";
    using var content = new StringContent("<data>Test</data>", Encoding.UTF8);
    using var response = await httpClient.PostAsync(urlValue , content);
    response.EnsureSuccessStatusCode();
    using var responseStream = await response.Content.ReadAsStreamAsync();
    using var decompressed = Constants.IsCompressed ?
                               new GZipStream(responseStream, CompressionMode.Decompress) :
                               responseStream;

    using var reader = new StreamReader(decompressed, Encoding.UTF8);
    var httpResponse = await readStream.ReadToEndAsync();
    return httpResponse;
}

话虽如此,您可能应该使用内置的自动压缩/解压缩。

builder.Services.AddResponseCompression(options =>
{
    options.EnableForHttps = true;
});
[HttpPost("[action]", Name = "GetData")]
public IActionResult GetData(string request)
{
     string data = GetStaticXMLFileData();
     return new ContentResult
     {
         Content = data,
         ContentType = "text/xml",
         StatusCode = (int)HttpStatusCode.OK,
     };
}

客户是:

static HttpClient _httpClient = new HttpClient(new HttpClientHandler
{
    AutomaticDecompression = DecompressionMethods.All,
});

private async Task<string> GetDataAPIResponse()
{
    var urlValue = $"https://localhost:44314/api/CompressedData/GetData?compress=true&result_format=xml";
    using var content = new StringContent("<data>Test</data>", Encoding.UTF8);
    using var response = await httpClient.PostAsync(urlValue , content);
    response.EnsureSuccessStatusCode();
    var httpResponse = await response.Content.ReadAsStringAsync();
    return httpResponse;
}
© www.soinside.com 2019 - 2024. All rights reserved.