zhoulei984623 发表于 2013-2-7 06:14:31

web中gzip,deflate的压缩与解压

一,对发送请求进行gzip,deflate压缩
1:gzip的情况
Sring url = "http://localhost/save";PostMethod post = new PostMethod(url);//请求体内容String body = "sample";//用gzip方式压缩请求体并赋给requestByteArrayInputStream bis = new ByteArrayInputStream(body.getBytes());ByteArrayOutputStream bos = new ByteArrayOutputStream();GZIPOutputStream gos = new GZIPOutputStream(bos);for (int c = bis.read(); c != -1; c = bis.read()) {    gos.write(c);}gos.close();InputStreamRequestEntity entity = new InputStreamRequestEntity(new ByteArrayInputStream(bos.toByteArray()), "text/html");post.setRequestEntity(entity);post.addRequestHeader("Content-Encoding", "gzip"); 
2:deflate的情况
Sring url = "http://localhost/save";PostMethod post = new PostMethod(url);//请求体内容String body = "sample";//用deflate方式压缩请求体并赋给requestByteArrayInputStream bis = new ByteArrayInputStream(body.getBytes());ByteArrayOutputStream bos = new ByteArrayOutputStream();DeflaterOutputStream dos = new DeflaterOutputStream(bos);for (int c = bis.read(); c != -1; c = bis.read()) {    dos.write(c);}dos.close();InputStreamRequestEntity entity = new InputStreamRequestEntity(new ByteArrayInputStream(bos.toByteArray()), "text/html");post.setRequestEntity(entity);post.addRequestHeader("Content-Encoding", "deflate"); 
二,在服务器端使用过滤器对压缩过的请求进行解压
新建一个filter继承UserAgentFilter.java,截取req,进行包装,接着继续执行别的filters
@Overridepublic void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,    ServletException {    HttpServletRequest request = (HttpServletRequest) req;    String ce = request.getHeader("Content-Encoding"); // gzip|deflate|inflate    if (ce != null) {      if (ce.indexOf("deflate") >= 0 || ce.indexOf("inflate") >= 0) {    // uncompress using inflate    request = new InflateRequestWrapper(request);      } else if (ce.indexOf("gzip") >= 0) {    // uncompress using gzip    request = new GZipRequestWrapper(request);      }    }    ......    super.doFilter(request, res, chain);    ......} 
下面是InflateRequestWrapper的内容,GZipRequestWrapper与之类似
public class InflateRequestWrapper extends HttpServletRequestWrapper {    private BufferedServletInputStreamWrapper _stream;    public InflateRequestWrapper(HttpServletRequest request) throws IOException {      super(request);      _stream = new BufferedServletInputStreamWrapper(new InflaterInputStream(request.getInputStream()), request.getContentLength());    }    @Override    public BufferedServletInputStreamWrapper getInputStream() {      return _stream;    }    @Override    public int getContentLength() {      return _stream.getBytes().length;    }} 
下面是BufferedServletInputStreamWrapper的内容
public class BufferedServletInputStreamWrapper extends ServletInputStream {    private static final int DEFAULT_READ_BUFFER_SIZE = 1024;    private final byte[] EMPTY_ARRAY = new byte;    private ByteArrayInputStream _is;    private byte[] _bytes;    /**   * takes in the actual input stream that we should be buffering   */    public BufferedServletInputStreamWrapper(InflaterInputStream stream, int length) throws IOException {      _bytes = (length == 0) ? EMPTY_ARRAY : toBytes(stream, length);      _is = new ByteArrayInputStream(_bytes);    }    @Override    public int read() throws IOException {      return _is.read();    }    @Override    public int read(byte[] buf,                  int off,                  int len) {      return _is.read(buf, off, len);    }    @Override    public int read(byte[] buf) throws IOException {      return _is.read(buf);    }    @Override    public int available() {      return _is.available();    }    /**   * resets the wrapper's stream so that it can be re-read from the stream. if we're   * using this somewhere were we expect it to be done again in the chain this should   * be called after we're through so we can reset the data.   */    public void resetWrapper() {      _is = new ByteArrayInputStream(_bytes);    }    public byte[] getBytes() {      return _bytes;    }    private byte[] toBytes(InputStream is, int bufferSize) throws IOException {      bufferSize = (bufferSize <= 0) ? DEFAULT_READ_BUFFER_SIZE : bufferSize;      ByteArrayOutputStream bos = new ByteArrayOutputStream();      byte[] buffer = new byte;      int read = is.read(buffer);      while (-1 != read) {            bos.write(buffer, 0, read);            read = is.read(buffer);      }      return bos.toByteArray();    }} 
三,服务器对response进行压缩可参考jetty相关源码
 
四,java客户端对压缩过的返回值进行解压
1,gzip的情况
GZIPInputStream gzip = new GZIPInputStream(post.getResponseBodyAsStream());StringBuffer out = new StringBuffer();byte[] b = new byte;for (int n; (n = gzip.read(b)) != -1;) {    out.append(new String(b, 0, n));}return out.toString(); 
2,deflate的情况
InflaterInputStream iis = new InflaterInputStream(post.getResponseBodyAsStream());contentLength = (contentLength <= 0) ? 1024 : contentLength;ByteArrayOutputStream bos = new ByteArrayOutputStream();byte[] buffer = new byte;int read = iis.read(buffer);while (-1 != read) {    bos.write(buffer, 0, read);    read = iis.read(buffer);}byte[] _bytes = (contentLength == 0) ? EMPTY_ARRAY : bos.toByteArray();ByteArrayInputStream _is = new ByteArrayInputStream(_bytes);StringBuffer out = new StringBuffer();byte[] b = new byte;for (int n; (n = _is.read(b)) != -1;) {    out.append(new String(b, 0, n));}return out.toString();
页: [1]
查看完整版本: web中gzip,deflate的压缩与解压