如何在客户端解压缩HTML页面

4

我有这段代理代码,是从这篇文章中取得的,创建为一个HttpHandler。

public void ProcessRequest(HttpContext context)
{
        string url = context.Request["url"];
        string contentType = context.Request["type"];

        // no buffering as we want to save memory
        context.Response.Buffer = false;

        // beging getting content
        using (WebClient client = new WebClient())
        { 

            // set content type if specified
            if (!string.IsNullOrEmpty(contentType))
            {
                client.Headers.Add(HttpRequestHeader.ContentType, contentType);
            }

            client.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
            client.Headers.Add(HttpRequestHeader.AcceptLanguage, "en-US");
            client.Headers.Add(HttpRequestHeader.UserAgent, "Mozilla/5.0 (Windows; U; Windows NT 6.0; " +
               "en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6");                
            client.Headers.Add(HttpRequestHeader.Accept, "*/*");

            // get that data
            byte[] data = client.DownloadData(url);

            if (!context.Response.IsClientConnected) return;

            // deliver content type, encoding and length as it
            // is received from the external url
            context.Response.ContentType = client.ResponseHeaders["Content-Type"];

            string contentEncoding = client.ResponseHeaders["Content-Encoding"];
            string contentLength = client.ResponseHeaders["Content-Length"];

            if (!string.IsNullOrEmpty(contentEncoding))
                context.Response.AppendHeader(HttpRequestHeader.ContentEncoding.ToString(), contentEncoding);

            if (!string.IsNullOrEmpty(contentLength))
                context.Response.AppendHeader(HttpRequestHeader.ContentLength.ToString(), contentLength);


            // transmit the exact bytes downloaded
            context.Response.BinaryWrite(data);


    }
}

我已将此 Http 模块映射为 IIS7 中的托管处理程序,并在我的纯 HTML 页面中使用 jQuery 调用代理并将结果放入 iframe。
$(document).ready(function() {
    $.ajax({
        type: "GET",
        url: "a.RegularProxy",
        data: { url: 'http://example.org/test.html', type: "text/html" },
        dataType: "html",
        success: function(data) {
            $("iframe").contents().find('html body').html(data.toString());
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            alert(errorThrown);
        }
    });
});

当页面简单时,一切都运行良好。但是,如果页面被压缩(gzip、deflate),我需要找到一种在客户端上解压缩它而不是在代理服务器上解压缩的方法——代理服务器的功能是尽可能快。

1个回答

3

浏览器会根据HTTP头自动进行解压缩。

我猜测发生的情况是WebClient在从上游服务器接收响应时自动解压缩。您的代码然后将解压缩的信息传输给客户端,但告诉客户端数据已经被压缩。

直接告诉WebClient不要解压缩是不可能的。您必须创建派生的WebClient类并覆盖GetWebRequest方法。在该方法中,您要告诉HttpWebRequest不要解压缩。代码如下:

public class MyWebClient: WebClient
{
    protected override WebRequest GetWebRequest(Uri address)
    {
        WebRequest wr = base.GetWebRequest(address);
        wr.AutomaticDecompression = DecompressionMethods.None;
        return wr;
    }
}

然后,您可以使用MyWebClient代替WebClient

using (MyWebClient client = new MyWebClient)
{
    // do your thing here
}

我不确定这是否是正确的情况,为了测试目的,我添加了一些额外的代码来在代理内执行解压缩 - 使用头部检查。之前未显示的HTML页面现在完全按照应该显示。这使我相信WebClient在将响应写入上下文对象之前没有自动解压缩。 - Rob
我建议在客户端编写一个测试程序,让您可以查看代理传输的原始数据。如果您关闭客户端上的自动解压缩功能,您可以完全按照传递的方式查看数据。这是您确切了解发生情况的唯一方法。此外,在代理上,我建议将接收到的字节写入文件并检查其内容。这样您就可以确切地知道发生了什么。 - Jim Mischel

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