HTTP方式传输Gzip(Java数据压缩)

1 篇文章 0 订阅
1 篇文章 0 订阅

场景:
客户端发送给服务端的数据过长,由于带宽受限及浏览速度的因素,需要压缩数据进行传输。
本文使用的压缩算法是Gzip,客户端压缩了以后再传输给服务端。
不是C到S,HTTP协议的两端也可以。

贴一下压缩的工具类CompressUtils

package com.yolanda.myspringboot.compress;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

/**
 * @Author:Yolanda
 * @Date: 2020/5/7 14:30
 */
public class CompressUtils {

    private static final String GZIP_ENCODE_UTF_8 = "UTF-8";
    private static final String GZIP_ENCODE_ISO_8859_1 = "ISO-8859-1";

    private static final int BYTE_NUM = 256;

    /**
     *
     * compress:压缩数据方法 <br/>
     * @param str
     *          String
     * @return
     *          String
     * @throws IOException
     *                 IOException
     */
    public static String compress(String str) throws IOException {
        return new String(compressData(str, GZIP_ENCODE_UTF_8), GZIP_ENCODE_ISO_8859_1);
    }
//    public static byte[] compress(String str) throws IOException {
//        return compressData(str, GZIP_ENCODE_UTF_8);
//    }

    /**
     *
     * decompressToStr:解压缩数据方法 <br/>
     * @param byteStr
     *          String
     * @return
     *          String
     */
    public static String decompressToStr(String byteStr) {
        byte[] bytes;
        try {
            bytes = byteStr.getBytes(GZIP_ENCODE_ISO_8859_1);
            return decompressDataToStr(bytes, GZIP_ENCODE_UTF_8);
        } catch (UnsupportedEncodingException e) {
            System.out.println("解压缩数据转码失败:" + e.getMessage());
        }
        return null;
    }

    /**
     *
     * compressData:压缩数据具体处理方法 <br/>
     * @param str
     *          String
     * @param encoding
     *          String
     * @return
     *          byte[]
     */
    public static byte[] compressData(String str, String encoding) {
        if (str == null || str.length() == 0) {
            return null;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        GZIPOutputStream gzip;
        try {
            gzip = new GZIPOutputStream(out);
            gzip.write(str.getBytes(encoding));
            gzip.close();
        } catch (IOException e) {
            System.out.println("压缩数据失败:" + e.getMessage());
        }
        return out.toByteArray();
    }

    /**
     *
     * decompressDataToStr:解压缩数据具体处理方法 <br/>
     * @param bytes
     *          byte[]
     * @param encoding
     *          String
     * @return
     *          String
     */
    public static String decompressDataToStr(byte[] bytes, String encoding) {
        if (bytes == null || bytes.length == 0) {
            return null;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ByteArrayInputStream in = new ByteArrayInputStream(bytes);
        try {
            GZIPInputStream ungzip = new GZIPInputStream(in);
            byte[] buffer = new byte[BYTE_NUM];
            int n;
            while ((n = ungzip.read(buffer)) >= 0) {
                out.write(buffer, 0, n);
            }
            return out.toString(encoding);
        } catch (IOException e) {
            System.out.println("解压缩数据失败:" + e.getMessage());
        }
        return null;
    }

}

这里需要注意的是,这个工具类如果不是发给服务端的,用这个注释掉的压缩方法没有问题

//    public static byte[] compress(String str) throws IOException {
//        return compressData(str, GZIP_ENCODE_UTF_8);
//    }

如果是要传输的就不能用UTF-8,要用ISO-8859-1编码方式。如果用UTF-8编码方式传输,服务端拿到的数据是空值。

上述的工具类CompressUtils ,两端都要写哦,一端用压缩方法,另一端用解压缩方法。

我再贴一下写的简单测试类吧,看一下压缩的效果。
Main.java

package com.yolanda.mycompressclient.compress;

import java.io.IOException;

/**
 * @Author:Yolanda
 * @Date: 2020/5/7 15:01
 */
public class Main {

    public static void main(String [] args){
        String test="test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890";
        System.out.println("压缩前长度" + test.length());

        try{
            String afterCompressStr = CompressUtils.compress(test);
            System.out.println("压缩后长度" + afterCompressStr.length());
        }catch (IOException e){
            System.out.println(e.getMessage());
        }
    }
}

控制台输出结果

在这里插入图片描述

用springboot写了简单的客户端和服务端做测试。
(用springboot写是因为方便简单,朋友你也可以用别的框架写)
也贴一下代码,主要是测试客户端压缩了数据能成功发给服务端,服务端可以成功解压出客户端发送过来的数据。

服务端很简单
HelloController类

package com.yolanda.myspringboot;

import com.yolanda.myspringboot.compress.CompressUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author:Yolanda
 * @Date: 2020/5/7 13:41
 */

@RestController
public class HelloController {

    @RequestMapping("/hello")
    @ResponseBody
    public String hello(String data){
        return "Hello, Yolanda!我在服务端接收到了你发送过来的数据,解压后是:"
                + CompressUtils.decompressToStr(data);
    }
}

这里在application.properties配置文件里把服务端的端口设置成8081(因为后面客户端默认的8080)

server.port=8081

客户端稍微复杂一丢丢

因为要发HTTP请求,所以用了springboot的http工具
springboot里面发http请求也,太太太太简单了吧

pom文件里写入依赖

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.10</version>
        </dependency>

新建一个HttpClient接口类

package com.yolanda.mycompressclient.http;

import org.springframework.http.HttpMethod;
import org.springframework.util.MultiValueMap;

/**
 * @Author:Yolanda
 * @Date: 2020/5/7 18:10
 */
public interface HttpClient {

    public String client(String url, HttpMethod method, MultiValueMap<String,String> params);
}

然后新建一个HttpClientImpl类去实现它

package com.yolanda.mycompressclient.http.impl;

import com.yolanda.mycompressclient.http.HttpClient;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

/**
 * @Author:Yolanda
 * @Date: 2020/5/7 18:11
 */
@Service
public class HttpClientImpl implements HttpClient {

    public String client(String url, HttpMethod method, MultiValueMap<String,String> params){

        RestTemplate template = new RestTemplate();
        return template.postForObject(url, params, String.class);
    }
}

在Controller层里来测试压缩吧

package com.yolanda.mycompressclient.controller;

import com.yolanda.mycompressclient.compress.CompressUtils;
import com.yolanda.mycompressclient.http.HttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;

/**
 * @Author:Yolanda
 * @Date: 2020/5/7 18:05
 */
@Controller
public class TestController {
    @Autowired
    HttpClient httpClient;

    @RequestMapping(value = "/compress")
    @ResponseBody
    public String hello(){
        String url = "http://localhost:8081/hello";
        HttpMethod method = HttpMethod.GET;
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        String test="test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890 test1234567890";
        String afterCompressStr = "";
        try {
            afterCompressStr = CompressUtils.compress(test);
        }catch (IOException e){
            System.out.println(e.getMessage());
        }

        params.add("data", afterCompressStr);

        String response = httpClient.client(url, method, params);
        System.out.println(response);
        return response;
    }
}

服务端和客户端一起跑起来
浏览器输入http://localhost:8080/compress
(这是客户端的)
收到了来自客户端的返回。

 

 

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小马哥@@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值