使用Gzip加速网页的传输

简介:

博学,切问,近思--詹子知 (https://jameszhan.github.io)

日前笔者在使用HttpClient在处理大数据请求的时候,在连续发请求的时候经常会出现异常 java.io.IOException: chunked stream ended unexpectedly。使用HttpMethod的abort方法也不能完全避免这种异常的出现,但是对于小数据的请求,这种异常就基本上难得一见了。对于同样的页面请求,如何减少网络的数据传输量呢。众所周知,现在大部分的Web Server都是支持数据的压缩传输的。要知道,一般的网页内容经过压缩,大小可以减少到原来的20%以下,而对于纯英文为网站,网页内容更是可以减少到原来内容的5%以下。而要使Web Server对数据进行压缩传输,只需要在请求头上加入Accept-Encoding:gzip, deflate。public HttpMethod createHttpMethod(String url, String type, NameValuePair[] params, String contentType) { HttpMethod method = null; if (type.equalsIgnoreCase("POST")) { method = new PostMethod(url); method.setRequestHeader("Content-Type", contentType); if(params != null){ ((PostMethod) method).setRequestBody(params); } } else { method = new GetMethod(url); if(params != null){ method.setQueryString(params); } } method.setRequestHeader("Accept-Encoding", "gzip, deflate"); return method; }

 

这个时候,如果你请求的Web Server支持Gzip,返回来的响应便是被压缩后的数据,那么把压缩后的数据解析成原来的网页内容便是客户端要做的事情了。对于当前的主流浏览器,都是支持对压缩数据自动解压的,而在我们的应用程序中,我们只要对象网页流稍作处理,便可以得到原来的网页内容。

protected String doSuccess(HttpMethod method) throws IOException { InputStream in = method.getResponseBodyAsStream(); Header contentEncodingHeader = method.getResponseHeader("Content-Encoding"); if (contentEncodingHeader != null) { String contentEncoding = contentEncodingHeader.getValue(); if (contentEncoding.toLowerCase(Locale.US).indexOf("gzip") != -1) { in = new GZIPInputStream(in); } } return decoder.decode(in); }

上一篇文章,我们介绍了如何检查文档输入流的编码,本节我们就可以利用上文的HtmlInputStreamDecoder类来把文档流来解析文档内容。完整的代码如下:

import java.io.IOException; import java.io.InputStream; import java.util.Locale; import java.util.zip.GZIPInputStream; import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.URI; import org.apache.commons.httpclient.URIException; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.log4j.Logger; public class HttpRequest { private static final Logger LOGGER = Logger.getLogger(HttpRequest.class); private HttpClient client; private HtmlInputStreamDecoder decoder; public HttpRequest() { this(new HttpClient(new MultiThreadedHttpConnectionManager())); } public HttpRequest(HttpClient client) { this.client = client; this.decoder = new HtmlInputStreamDecoder(); } public String doRequest(HttpMethod method) { String html = null; try { int statusCode = client.executeMethod(method); switch (statusCode) { case HttpStatus.SC_OK: html = doSuccess(method); break; case HttpStatus.SC_MOVED_PERMANENTLY: case HttpStatus.SC_MOVED_TEMPORARILY: case HttpStatus.SC_SEE_OTHER: case HttpStatus.SC_TEMPORARY_REDIRECT: doRedirect(method); break; default: html = doError(method); } } catch (HttpException e) { LOGGER.error("Http error occur while visit the url.", e); } catch (IOException e) { LOGGER.error("IO error occur while visit the url.", e); } finally { method.abort(); method.releaseConnection(); } return html; } protected String doSuccess(HttpMethod method) throws IOException { InputStream in = method.getResponseBodyAsStream(); Header contentEncodingHeader = method.getResponseHeader("Content-Encoding"); if (contentEncodingHeader != null) { String contentEncoding = contentEncodingHeader.getValue(); if (contentEncoding.toLowerCase(Locale.US).indexOf("gzip") != -1) { in = new GZIPInputStream(in); } } return decoder.decode(in); } protected String doError(HttpMethod method) { LOGGER.error("Error Response: " + method.getStatusLine()); return method.getStatusText(); } protected void doRedirect(HttpMethod method) throws URIException { Header locationHeader = method.getResponseHeader("location"); if (locationHeader != null) { String location = locationHeader.getValue(); if (location == null) { location = "/"; } doRequest(new GetMethod(getRedirectUrl(method.getURI(), location))); } } public HttpMethod createHttpMethod(String url, String type, NameValuePair[] params, String contentType) { HttpMethod method = null; if (type.equalsIgnoreCase("POST")) { method = new PostMethod(url); method.setRequestHeader("Content-Type", contentType); if(params != null){ ((PostMethod) method).setRequestBody(params); } } else { method = new GetMethod(url); if(params != null){ method.setQueryString(params); } } method.setRequestHeader("Accept-Encoding", "gzip, deflate"); return method; } protected static String getRedirectUrl(URI origin, String location) throws URIException { String redirect = null; if (location.startsWith("http:")) { redirect = location; } else if (location.startsWith("/")) { origin.setPath(location); redirect = origin.getURI(); } else { redirect = origin.getURI().replaceAll("(?<=/)[^/]+$", location); } return redirect; } }

 

代码示例:

public static void main(String[] args) { HttpRequest request = new HttpRequest(); HttpMethod method = request.createHttpMethod("http://www.csdn.com", "GET", null, "text/html"); String html = request.doRequest(method); System.out.println(html); }

 

目录
相关文章
|
5月前
|
缓存 应用服务中间件 nginx
Web服务器的缓存机制与内容分发网络(CDN)
【8月更文第28天】随着互联网应用的发展,用户对网站响应速度的要求越来越高。为了提升用户体验,Web服务器通常会采用多种技术手段来优化页面加载速度,其中最重要的两种技术就是缓存机制和内容分发网络(CDN)。本文将深入探讨这两种技术的工作原理及其实现方法,并通过具体的代码示例加以说明。
519 1
|
算法 应用服务中间件 nginx
nginx开通gzip压缩传输文件
nginx开通gzip压缩传输文件
|
8月前
BurpSuite2022.1(分块传输)
BurpSuite2022.1(分块传输)
126 0
|
存储 网络协议
<4>[QTCN]图片网络传输工具(服务器端)
说明:图片网络传输工具(服务器端)。 亮点:图片网络传输解码。
84 0
|
CDN
CDN的页面优化、GZIP和range回源
CDN的页面优化、GZIP和range回源自制脑图
107 0
CDN的页面优化、GZIP和range回源
|
移动开发 缓存 前端开发
前端性能优化 - 静态资源合并与压缩减少HTTP请求
这是一个基于.Net Core开发的,实现压缩Css、Javascript、Html资源的压缩、合并功能的组件。通过这个组件我们就可以实现静态资源的捆绑,实现对js、css、less、scss等静态资源的自动打包捆绑处理。
328 0
前端性能优化 - 静态资源合并与压缩减少HTTP请求
|
缓存 网络协议 算法
Http实战之编码、分块传输、范围请求
Http实战之编码、分块传输、范围请求
514 0
Http实战之编码、分块传输、范围请求
|
数据安全/隐私保护 开发者 CDN
CDN 的页面优化、GZIP 和 range 回源| 学习笔记
快速学习 CDN 的页面优化、GZIP 和 range 回源。
CDN 的页面优化、GZIP 和 range 回源| 学习笔记
|
开发框架 .NET PHP
JavaWeb - 网页 GZIP 压缩检测
JavaWeb - 网页 GZIP 压缩检测
143 0
|
监控 算法 Cloud Native
开发函数计算的正确姿势——使用 brotli 压缩大文件
函数计算对上传的 zip 代码包尺寸限制为 50M。某些场景中代码包中会超过这一限制,比如未经裁剪的 serverless-chrome,类似的还有 libreoffice ,此外常见的还有机器学习训练的模型文件。本文会比较几种常见的解决大文件的方案,并重点介绍借助 brotli 提高压缩比的方法。
开发函数计算的正确姿势——使用 brotli 压缩大文件

热门文章

最新文章

下一篇
开通oss服务