通过WebClient.DownloadData自动解压gzip响应

52

我希望能够自动解压缩 GZip 压缩的响应。 我正在使用以下代码片段:

mywebclient.Headers[HttpRequestHeader.AcceptEncoding] = "gzip";
mywebclient.Encoding = Encoding.UTF8;

try
{
    var resp = mywebclient.DownloadData(someUrl);
}

我已经查看了HttpRequestHeader枚举,但是没有选项可以通过Headers来完成这个任务。

我该如何自动解压缩响应?或者是否有其他函数可以代替mywebclient.DownloadData

2个回答

124

WebClient使用HttpWebRequest作为基础工具。而HttpWebRequest支持gzip/deflate解压缩。请参阅HttpWebRequest AutomaticDecompression属性

然而,WebClient类没有直接公开此属性。因此,您将需要从它派生出来并在底层的HttpWebRequest上设置该属性。

class MyWebClient : WebClient
{
    protected override WebRequest GetWebRequest(Uri address)
    {
        HttpWebRequest request = base.GetWebRequest(address) as HttpWebRequest;
        request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
        return request;
    }
}

23
在这里使用“过度使用”(在我看来)的as-casting而不是“传统的casting”,是否有特定的原因?如果您使用as,您肯定应该检查请求是否为非null,因此我想知道在这种情况下假设GetWebRequest()的结果始终为HttpWebRequest是否会更简单。 - Per Lundberg
很遗憾,这对于WP8.1 Silverlight项目不起作用。属性“AutomaticDecompression”不可用。有什么想法应该怎么做吗?谢谢! - casaout

32

根据您的情况,自己进行解压可能会更简单。

using System.IO.Compression;
using System.Net;

try
{
    var client = new WebClient();
    client.Headers[HttpRequestHeader.AcceptEncoding] = "gzip";
    var responseStream = new GZipStream(client.OpenRead(myUrl), CompressionMode.Decompress);
    var reader = new StreamReader(responseStream);
    var textResponse = reader.ReadToEnd();

    // do stuff

}

为了清晰明了,我创建了所有临时变量。这可以简化为仅使用clienttextResponse

或者,如果简单是目标,你甚至可以使用Demis Bellot的ServiceStack.Text来做到这一点:

using ServiceStack.Text;

var resp = "some url".GetJsonFromUrl();

(还有其他.Get*FromUrl扩展方法)


我不确定client.OpenRead是否尊重为webClient实例设置的编码。 - chester89
需要指出的一点是:您必须实际“读取”gzip流以便进行解压缩;尝试使用类似于responseStream.CopyTo( File.OpenWrite(...) )这样的方法并不起作用。 - drzaus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接