首页 > 解决方案 > 2个不同的aspnet核心webapi `Actions`上的2个不同的`Content-Encoding`

问题描述

我有Controller1/Action1,目前不关心Accept-Encoding请求和返回application/json响应。

现在在同一个应用程序中,我们正在添加Controller2/Action2,它将返回巨大的 json (~5mb) 并且想要使用压缩并决定使用gzip. 我们new client_2已经Controller2/Action2准备好将其作为gzip.

虽然Controller1/Action1仍然必须返回Content-Encodingasapplication/json和 NOT gzip,因为我不认为所有client_1sController1/Action1passAccept-Encoding标题。

那么我怎样才能在 2 differentContent-Encoding上实现 2 different Actions

在 aspnet 管道中添加以下压缩会导致所有操作的 gzip 并且不会返回我总是想要JSONController1/Action1,因为我不认为所有人client_1s都有能力消费gzip

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddResponseCompression(options => { options.EnableForHttps = true; });
            services.Configure<GzipCompressionProviderOptions>(options =>
            {
                options.Level = CompressionLevel.Optimal;
            });
        }

仅在 Action 上添加以下属性似乎也没有任何效果,我没有得到任何回复

[Produces("application/gzip")]

标签: asp.net-web-apigzipcontent-encoding

解决方案


如果使用 GZip 压缩,Action Controller2/Action2 总是以二进制格式返回数据。因此,您必须将响应标头中的“内容编码”更改为二进制。例如,在响应标头中,尝试给出以下内容

Content-Encoding: gzip
Vary: Accept Encoding

在请求标头中,给出以下内容,

Accept-Encoding: br, compress, gzip 

还有另一种方法,您可以使用以下代码将压缩的二进制文件转换为字符串,这将被接受 JSON 的客户端接受。

using (var stream = new MemoryStream())
        {
            using (var zip = new GZipStream(stream, CompressionMode.Compress, true))
            {
                var formatter = new BinaryFormatter();
                formatter.Serialize(zip, list);
            }
            var byteArray = stream.ToArray();
            StringBuilder sb = new StringBuilder();
            foreach (byte item in byteArray)
            {
                sb.Append((char)item);
            }
            return sb.ToString();
        }

推荐阅读