Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

前端如何压缩 HTTP 请求正文-针对请求体数据量大 #6

Open
FanFanJUN opened this issue Oct 9, 2021 · 1 comment
Open

Comments

@FanFanJUN
Copy link
Owner

如何压缩 HTTP 请求正文

pako.js对数据进行gzip压缩传递到后台解析,解决数据量大的请求问题

import pako from 'pako';

export const addCalibration = (params) => {
    const sendData = dealDataToGzip(params);
    return httpUtils.postJsonForGzip(WinBidApproveBaseUrl + "/calibrationHeadInfo/insert", sendData)
};

export function dealDataToGzip(params) {
    let secparams = encodeURIComponent(JSON.stringify(params));
    const compressBeginLen = secparams.length;
    if (compressBeginLen > 1000) {
        //对 JSON 字符串进行压缩
        // pako.gzip(params) 默认返回一个 Uint8Array 对象,如果此时使用 Ajax 进行请求,参数会以数组的形式进行发送
        // 为了解决该问题,添加 {to: "string"} 参数,返回一个二进制的字符串
        secparams = {sendGzipData: pako.gzip(secparams), isGzip: true};
    } else {
        secparams = {sendGzipData: params, isGzip: false};
    }
    return secparams;
}

axios 实例请求
postJsonForGzip(url,data={}){
        return new Promise((resolve,reject) => {
            instance({
                method: 'post',
                data: data.sendGzipData,
                headers: data.isGzip ?{...getHeader(), 'Content-Encoding': 'gzip'} : getHeader(),
                url,
                params:Date.parse(new Date()),
            }).then(res => {
                resolve(res)
            }).catch(err =>{
                message.error(err.messageCode)
                reject(err)
            })
        })
    },
 /**
     * 解析数据
     *
     */

    public xxx( HttpServletRequest request) {
        //从request中获取参数对象,支持gzip压缩格式
       GzipUtil.getObjFromRequest(request, CalibrationHeadInfoBo.class);
    }
 
    
package com.ecmp.srm.wa.util;

import com.ecmp.log.util.LogUtil;
import com.ecmp.util.JsonUtils;
import org.apache.commons.compress.utils.IOUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.List;
import java.util.Objects;
import java.util.zip.GZIPInputStream;

/**
 * 对请求中压缩的参数进行解压
 * @author lifei
 * @Date 2021/6/24 15:32
 */
public class GzipUtil {

    //Spring方法参数不能包含@RequestBody,否则无法获取到参数
    public static <T> T getObjFromRequest(HttpServletRequest request,Class<T> clazz){
        try {
            String params = getStringFromRequest(request);
            if (Objects.nonNull(params) && params.trim().length() > 0) {
                //因为前台对参数进行了 url 编码,在此进行解码
                params = params.replaceAll("%(?![0-9a-fA-F]{2})", "%25").replaceAll("\\+", "%2B");
                params = URLDecoder.decode(params, "utf-8");
                //将解码后的参数转换为 json 对象
                return JsonUtils.fromJson(params,clazz);
            }
        } catch (IOException e) {
            e.printStackTrace();
            LogUtil.error("压缩参数解析错误",e);
        }
        return null;
    }

    //Spring方法参数不能包含@RequestBody,否则无法获取到参数
    public static <T> List<T> getListFromRequest(HttpServletRequest request, Class<T> clazz){
        try {
            String params = getStringFromRequest(request);
            if (Objects.nonNull(params) && params.trim().length() > 0) {
                //因为前台对参数进行了 url 编码,在此进行解码
                params = params.replaceAll("%(?![0-9a-fA-F]{2})", "%25").replaceAll("\\+", "%2B");
                params = URLDecoder.decode(params, "utf-8");
                //将解码后的参数转换为 json 对象
                return JsonUtils.fromJson2List(params,clazz);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static String getStringFromRequest(HttpServletRequest request) throws IOException {
        //将输入流中的请求实体转换为byte数组,进行gzip解压
        byte[] bytes = IOUtils.toByteArray(request.getInputStream());
        //获取 Content-Encoding 请求头
        String contentEncoding = request.getHeader("Content-Encoding");
        if (contentEncoding != null && contentEncoding.equals("gzip")) {
            //对 bytes 数组进行解压
            return uncompress(bytes);
        } else {
            return new String(bytes);
        }
    }

    private static String uncompress(byte[] bytes) throws IOException {
        if (Objects.isNull(bytes) || bytes.length == 0) {
            return null;
        }
        ByteArrayOutputStream byteArrayOutputStream = null;
        ByteArrayInputStream byteArrayInputStream = null;
        GZIPInputStream gzipInputStream = null;
        try {
            byteArrayInputStream = new ByteArrayInputStream(bytes);
            gzipInputStream = new GZIPInputStream(byteArrayInputStream);
            //使用org.apache.commons.io.IOUtils 简化流的操作
            byteArrayOutputStream = new ByteArrayOutputStream();
            IOUtils.copy(gzipInputStream, byteArrayOutputStream);
            return byteArrayOutputStream.toString("utf-8");
        } catch (IOException e) {
            throw e;
        } finally {
            //释放流资源
            IOUtils.closeQuietly(gzipInputStream);
            IOUtils.closeQuietly(byteArrayInputStream);
            IOUtils.closeQuietly(byteArrayOutputStream);
        }
    }
}
    
@ZhangXDong
Copy link

有没有 node版本的解压缩代码,感谢~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants