在HttpClient中解压缩Brotli HttpResponse

时间:2019-07-15 11:27:34

标签: c# .net-core dotnet-httpclient

我有一个Web Api,向我发送的响应用brotli压缩,我有一个控制台应用程序,它通过向我的WebApi请求数据来使用HttpClient。我需要解压缩WebApi发送的数据。

对于.Net Core 2.2

Startup.cs

//对服务器的保留权

services.Configure<BrotliCompressionProviderOptions>(opciones =>
                opciones.Level = CompressionLevel.Optimal
);

services.AddResponseCompression(opciones =>
{
    opciones.EnableForHttps = true;
    opciones.Providers.Add<BrotliCompressionProvider>();
});

ConseleApp

using (var client = new HttpClient(handler)){
    client.BaseAddress = new Uri(BASE_URL);
    client.Timeout = new TimeSpan(0, 0, TIMEOUT_SECONDS);
    HttpRequestHeaders headers = client.DefaultRequestHeaders;
    headers.Add("X-User", Environment.UserName);
    headers.Add("Accept-Encoding", "br"); //gzip
    HttpResponseMessage response = null;

    response = await client.GetAsync($"{requestUrl}");
    if (response.IsSuccessStatusCode)
    {
        string strResult = await response.Content.ReadAsStringAsync();
        return JsonConvert.DeserializeObject<T>(strResult);
    }
}

strResult不是JSON。 。

3 个答案:

答案 0 :(得分:1)

假设您使用的是.NET Core 2.1中包含的HttpClientFactory,那么您可以创建一个委托处理程序,该处理程序将在将完整的有效内容传递给代码之前对其进行拦截和解压缩。

using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using BrotliSharpLib;

public class BrotliCompressionHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        var response = await base.SendAsync(request, cancellationToken);
        if (!response.Content.Headers.TryGetValues("Content-Encoding", out var ce) 
          || ce.First() != "br")
            return response;
        var buffer = await response.Content.ReadAsByteArrayAsync();
        response.Content = new ByteArrayContent(
          Brotli.DecompressBuffer(buffer, 0, buffer.Length));
        return response;
    }
}

然后将处理程序连接到需要支持brotli的客户端。

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddTransient<BrotliCompressionHandler>()
        .AddHttpClient("github", c =>
        {
            c.BaseAddress = new Uri("https://api.github.com/");
            c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
            c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
        })
        .AddHttpMessageHandler<BrotliCompressionHandler>();
}

答案 1 :(得分:0)

您尝试过以下.Net库之一吗?

  1. https://www.nuget.org/packages/Brotli.NET/
  2. https://www.nuget.org/packages/BrotliSharpLib/

都支持Brotli压缩和解压缩,而无需.Net本机支持。他们声称也比.Net实施要快。

答案 2 :(得分:0)

我已经通过Brotli.NET实现了以下目标:

static async Task<string> GetLinkTitle(string link) => await Task.Run(async () =>
{
    using (var httpGet = new System.Net.Http.HttpClient())
    {
        httpGet.DefaultRequestHeaders.Add("Accept-Encoding", "br");
        var response = await httpGet.GetAsync($"http://www.youtube.com/oembed?url={link}&format=xml");
        
        string responseContent;
        using(var brotli = new Brotli.BrotliStream(await response.Content.ReadAsStreamAsync(), System.IO.Compression.CompressionMode.Decompress, true))
        {
            var streamReader = new StreamReader(brotli);
            responseContent = streamReader.ReadToEnd();
        }

        var doc = XDocument.Parse(responseContent);
        return !response.IsSuccessStatusCode ? $"ERROR: {response.StatusCode} - {link}".Dump() : doc.Descendants("title").FirstOrDefault().Value;
    }
});