您的当前位置:首页正文

GZip介绍

2020-10-25 来源:步旅网
使用GZip

一、使用GZip压缩/解压缩文件: 1.1 Java对GZip的支持

虽然网上可以找到GZip的应用程序,但是由于是用C++编写的,且是dos命令行的方式,使用方面有一些限制,而实际上,Java也提供了GZip的支持,示例代码如下:

/** * 将数据压缩成GZip格式的数据 */ public static void compress(InputStream is, OutputStream os) } /** * GZip格式数据解压缩 */ public static void decompress(InputStream is, OutputStream os) throws Exception { } GZIPInputStream gis = new GZIPInputStream(is); int count; byte data[] = new byte[BUFFER]; while ((count = gis.read(data, 0, BUFFER)) != -1) { } gis.close(); os.write(data, 0, count); throws Exception { GZIPOutputStream gos = new GZIPOutputStream(os); int count; byte data[] = new byte[BUFFER]; while ((count = is.read(data, 0, BUFFER)) != -1) { } gos.finish(); gos.flush(); gos.close(); gos.write(data, 0, count);

1.2 用Java将文件夹中的js文件压缩

如果需要遍历某一文件夹,将其中指定格式的文件压缩成GZip格式的文件,完全可以用遍历文件夹的方式来处理。下面的代码将遍历文件夹,将其中的.js文件压缩成GZip格式文件后,并同时将后缀名更改为.gzjs(注:1.下面的代码为我自己写的,可能有某方面的不足;2.可将gzjs格式文件的默认打开方式为winrar,可以用winrar直接解压)

/** * 压缩文件夹,如是js格式,则压缩为.gzjs,如果不是原样复制! * @param folderFrom 要压缩的文件夹 * @param folderTo 目标文件夹 * @param compressSonFolder 是否压缩子文件夹 * @throws Exception */ public static void compressJsFolder(File folderFrom,File folderTo,boolean compressSonFolder) throws Exception{ File[]files=folderFrom.listFiles(); for(int i=0;i0?(fileTo.length()*100/fileFrom.length()+\"%\"):(fileTo.length()+\"/\"+fileFrom.length()); System.out.println(\"\压缩前大小为:\"+fileFrom.length()+\",压缩后大小为:\"+fileTo.length()+\",压缩比为:\"+compare); }else{ } fileTo=new File(folderTo,fileFrom.getName()); copyFile(fileFrom,fileTo); System.out.println(fileFrom.getPath()+\"不是js文件,已直接复制!\"); } if(files[i].isDirectory()){ if(compressSonFolder){ } } } File sonFolderFrom=files[i]; File sonFolderTo=new File(folderTo,files[i].getName()); compressJsFolder(sonFolderFrom,sonFolderTo,compressSonFolder); } /** * 文件压缩,生成gzip格式的文件 * @param fileFrom 原始文件(要压缩的文件) * @param fileTo 要生成的压缩文件 * @param delete 是否要删除原始文件 * @throws Exception */ public static void compress(File fileFrom ,File fileTo,boolean } /** * 判断给定的文件是否是js文件 */ private static boolean isJsFile(File file) { } public static void copyFile(File fileFrom, File fileTo) { try { return file.getName().endsWith(\".js\"); FileInputStream fis = new FileInputStream(fileFrom); FileOutputStream fos = new FileOutputStream(fileTo); compress(fis, fos); fis.close(); fos.flush(); fos.close(); if (delete) { } fileFrom.delete(); delete)throws Exception{ if (fileFrom.exists()) { //文件存在时 InputStream inStream = new FileInputStream(fileFrom); //读入原文件 FileOutputStream fs = new FileOutputStream(fileTo); byte[] buffer = new byte[BUFFER]; int byteread=0; while ( (byteread = inStream.read(buffer)) != -1) { fs.write(buffer, 0, byteread); } inStream.close(); } } catch (Exception e) { e.printStackTrace(); } }

1.3、单独的一个Servlet使用GZip

只需要加入下面的一句代码: response.setHeader(\"Content-Encoding\参考信息:

《Java压缩技术(五) GZIP相关——浏览器解析》

二、将GZip用到项目中(不建议!) 2.1创建GZip过滤器

下面的过滤器是从网上找的,功能就是在response的文件头中加入“Cntent-Encoding=gzip”。

package yupont.pf.util; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class GzipJsFilter implements Filter { } public void init(FilterConfig config) throws ServletException { } String headersStr = config.getInitParameter(\"headers\"); String[] headers = headersStr.split(\); for (int i = 0; i < headers.length; ++i) { } String[] temp = headers[i].split(\"=\"); this.headers.put(temp[0].trim(), temp[1].trim()); } FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding(\"UTF-8\"); for (Iterator it = this.headers.entrySet().iterator(); } chain.doFilter(request, response); Map.Entry entry = (Map.Entry) it.next(); response.addHeader((String) entry.getKey(), (String) entry .getValue()); public void doFilter(HttpServletRequest request, HttpServletResponse response, throws IOException, ServletException { } if (req instanceof HttpServletRequest) doFilter((HttpServletRequest) req, (HttpServletResponse) public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) public void destroy() { } Map headers = new HashMap(); res, chain); else chain.doFilter(req, res); it.hasNext();) {

2.2 web.xml中添加过滤器配置信息

以项目“短信平台”为例,web.xml所在位置为:/webitem/WebContent/WEB-INF/web.xml。 (下面的这个配置信息中,gzjs为.js文件被GZip压缩后,将其后缀更改为.gzjs;而.gzjpg则为.jpg文件用GZip压缩后,将其后缀更改为的.gzjpg。)

web.xml中添加如下信息:

GzipJsFilter yupont.pf.util.GzipJsFilter headers Content-Encoding=gzip GzipJsFilter *.gzjs GzipJsFilter *.gzjpg GzipJsFilter *.gzpng

2.3 压缩文件,并修改其引用信息

用GZip压缩需要压缩的文件,并更改其相应的后缀,并在其引用的位置修改相应的引用信息。

仍然以“短信平台”为例,如其登陆页面/webitem/WebContent/appmsn/login.htm中有如下js文件的引用

type=\"text/javascript\" 现在已将其项目中的所有js均压缩并更改后缀为.gzjs,则此处应该改为:

type=\"text/javascript\" 然而,globalFunc.gzjs中也有引用其他的.js文件,如:jquery-1.4.4.min.js、utilComboBoxLoadData.js,而现在这些文件均已经被替换成了同名,但是后缀为.gzjs的文件,所以,需要把globalFunc.gzjs重新解压,修改其中相应的地方,再重新压缩。

2.4测试信息

(因为51.9挂了,所以无法连上数据库,只能测单个页面,测试页面详情:webitem项目,主页,其引用的js压缩后其后缀更改为.gzjs,其引用的jpg图片压缩后其后缀更改为.gzjpg)

测试工具:IETestv0.5.2

经初步测试,使用了gzjs、gzjpg的主页在IE5模式下报“Script error”!在IE8、IE9下图片未显示出来!

测试工具:IE9,版本号:9.0.8112.16421

经初步测试,“浏览器模式”使用IE7模式、IE8模式、IE9模式均未报错!,不过“文档模式”,只有在“Quick模式”下才不会出现排版错误!

测试工具:谷歌chrome,版本:31.0.1650.63 m 经初步测试,未发现异常。 测试工具:FireFox ,版本:26.0 经初步测试,未发现异常。

测试工具:Opera ,版本:18.0.1284.68 经初步测试,未发现异常。 测试工具:遨游, 版本:4.2.0.4000

经初步测试,未发现异常。

测试工具:360浏览器, 版本:6.2.1.200 经初步测试,未发现异常。

结论:可能会在某些较低版本的IE浏览器中显示不正常!

三、使用tk-filters 3.1 tk-filters简介

Tk-filters是我在网上搜到的一个带源码的过滤器。

实现GZip压缩的机制是:拦截response的包,并对其中的数据进行压缩,再发送出去。为了实现该功能,它自定义了一个HttpServletResponseWrapper的子类,该类使用ByteArrayOutputStream来操作数据。

public class GenericResponseWrapper extends HttpServletResponseWrapper { private ByteArrayOutputStream output; …… public GenericResponseWrapper(HttpServletResponse response) { super(response); output = new ByteArrayOutputStream(); } public byte[] getData() { return output.toByteArray(); } …… }

在该过滤器中,首先创建了GenericResponseWrapper,再从GenericResponseWrapper中将response的数据读取出来,经过GZip压缩,并在头文件中添加gzip识别信息。

该过滤器主要代码如下:父类com.tacitknowledge.filters.GenericFilter的过滤方法:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { doFilterInternal((HttpServletRequest) request, (HttpServletResponse) response, chain); } 子类com.tacitknowledge.filters.gzipfilter.GZIPFilter的过滤方法的实现

public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { if (isEnabled()) { response.addHeader(\"Vary\", ACCEPT_ENCODING); GenericResponseWrapper wrapper = new GenericResponseWrapper(response); chain.doFilter(request, wrapper); OutputStream out = response.getOutputStream(); if (!isCached(wrapper) && !isIncluded(request) && acceptsGzip(request)) { byte[] compressedData = compressData(wrapper.getData()); response.setHeader(CONTENT_ENCODING, \"gzip\"); response.setContentLength(compressedData.length); out.write(compressedData); } else { // we can't compress this data, just write it straight through out.write(wrapper.getData()); } // make sure all the data made it to the client out.flush(); out.close(); } else { chain.doFilter(request, response); } } protected byte[] compressData(byte[] data) throws IOException { // do the compression ByteArrayOutputStream compressed = new ByteArrayOutputStream(); GZIPOutputStream gzout = new GZIPOutputStream(compressed); gzout.write(data); gzout.flush(); gzout.close(); // If statistics are desired, compute them and log them out if (getBooleanConfigEntry(\"GZIPFilter.LogStats\")) { StringBuffer stats = new StringBuffer(\"\" + data.length); stats.append(\" / \" + compressed.size()); stats.append(\" / \" + (data.length - compressed.size())); if (data.length > 0) { double doubleRatio = (double) compressed.size() / (double) data.length; int ratio = (int) (doubleRatio * 100); stats.append(\" / \" + ratio + \"%\"); } else { stats.append(\" / NaN\"); } getFilterConfig().getServletContext().log( \"GZIPFilter: Original / GZip / Saved / Ratio: \" + stats); } return compressed.toByteArray(); }

3.2 tk-filter使用

一,首先,下载tk-filters-1.0.1.zip

二,解压这个tk-filters-1.0.1.zip压缩文件 ;

三,将解压后的文件tk-filters.jar放在Ext项目的WEB-INF/lib/下

四,打开解压后的文件夹tk-filters\\conf\k-filters.properties

GZIPFilter.Enabled=false(默认为false,true打开GZIP压缩功能) GZIPFilter.LogStats=false(默认为false,true打开GZIP压缩功能日志,可以在后台看到压缩比例信息) CacheFilter.Enabled=false(默认为false,true打开GZIP缓存功能) 注:可以自行选择想打开的功能,再将此文件复制到Ext项目的WEB-INF/class文件夹下(我是把该配置文件放到项目目录src下面)

com.tacitknowledge.filters.GenericFilter读取配置文件,具体代码如下: public abstract class GenericFilter implements Filter { private static final String CONFIG_FILE = \"tk-filters.properties\"; …… }

五,打开Ext项目的WEB-INF/web.xml文件

GZIPFilter com.tacitknowledge.filters.gzipfilter.GZIPFilter GZIPFilter *.js CacheFilter com.tacitknowledge.filters.cache.CacheHeaderFilter CacheFilter *.gif CacheFilter *.jpg CacheFilter *.png CacheFilter *.js CacheFilter *.css 3.3补充信息(参见2.4) 3.4测试信息

(因为51.9挂了,所以无法连上数据库,只能测单个页面,测试项目为enplatform,测试页为主页,tk-filter过滤器启用了对js、jpg压缩)

测试工具:IETestv0.5.2

经初步测试,使用了的主页在IE5模式下报“Script error”,更进一步导致IE5挂掉!在IE6下图片未显示出来!

测试工具:IE9,版本号:9.0.8112.16421

经初步测试,“浏览器模式”使用IE7模式、IE8模式、IE9模式均未报错!,不过“文档模式”,在“Quick模式”下会出现排版错误!

测试工具:谷歌chrome,版本:31.0.1650.63 m 经初步测试,未发现异常。 测试工具:FireFox ,版本:26.0 经初步测试,未发现异常。

测试工具:Opera ,版本:18.0.1284.68 经初步测试,未发现异常。 测试工具:遨游, 版本:4.2.0.4000 经初步测试,未发现异常。

测试工具:360浏览器, 版本:6.2.1.200 经初步测试,未发现异常。

结论:可能会在某些较低版本的IE浏览器中显示不正常!

四、配置Tomcat启用GZip压缩

配置Tomcat,启用其对GZip的支持。

修改Tomcat目录下conf/server.xml中的Connector节点:

1) compression=\"on\" 打开压缩功能

2) compressionMinSize=\"2048\" 启用压缩的输出内容大小,这里面默认为2KB 3) noCompressionUserAgents=\"gozilla, traviata\" 对于以下的浏览器,不启用压缩 4) compressableMimeType=\"text/html,text/xml\" 压缩类型

因篇幅问题不能全部显示,请点此查看更多更全内容