文章目錄
- 1)、springboot的gzip壓縮-滿足2k數據自動壓縮
- 1.1后端壓縮
- 1.2前端解壓
- 1.3 滿足最小響應大小(2KB)和指定MIME類型的響應進行GZIP壓縮
- yml配置
- 自定義配置或者使用Java配置
- 2)、gzip壓縮
- 1.1接口使用-數據壓縮發送前端
- 1.2 接口使用-數據解壓來自前端來的壓縮數據
- 1.3 GzipUtils工具類
- 3)、前端壓縮數據
- 1.2 實現GzipUtils類
- 1.3 前端使用示例
- 4)、zip壓縮方案
- 接口使用-數據壓縮發送前端
- 接口使用-數據解壓來自前端來的壓縮數據
- ZipUtils工具類
1)、springboot的gzip壓縮-滿足2k數據自動壓縮
1.1后端壓縮
@GetMapping(value = "/data", produces = "application/json")public void getData(HttpServletResponse response) throws IOException {String data = "your large data here"; // Replace with actual large dataresponse.setHeader("Content-Encoding", "gzip");response.setContentType("application/json");try (OutputStream os = response.getOutputStream();GZIPOutputStream gzipOutputStream = new GZIPOutputStream(os)) {gzipOutputStream.write(data.getBytes());}}
1.2前端解壓
fetch('/api/data', {headers: {'Accept-Encoding': 'gzip'}
})
.then(response => {if (response.ok) {return response.blob();}throw new Error('Network response was not ok.');
})
.then(blob => {const reader = new FileReader();reader.onload = () => {const decompressedData = pako.inflate(reader.result, { to: 'string' });console.log(JSON.parse(decompressedData));};reader.readAsArrayBuffer(blob);
})
.catch(error => {console.error('There was a problem with your fetch operation:', error);
});
1.3 滿足最小響應大小(2KB)和指定MIME類型的響應進行GZIP壓縮
將為JSON、XML、文本和JavaScript以及CSS等類型的響應啟用GZIP壓縮,并且響應大小至少需要2KB才會被壓縮
yml配置
# application.yml
server:compression:enabled: truemime-types: application/json,application/xml,text/html,text/xml,text/plain,application/javascript,text/cssmin-response-size: 2048
自定義配置或者使用Java配置
創建了一個ShallowEtagHeaderFilter bean和一個GzipCompressingFilter bean,后者會對滿足最小響應大小(2KB)和指定MIME類型的響應進行GZIP壓縮
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.web.filter.ShallowEtagHeaderFilter;import java.util.Arrays;
import java.util.List;@Configuration
public class GzipConfig {@Beanpublic ShallowEtagHeaderFilter shallowEtagHeaderFilter() {return new ShallowEtagHeaderFilter();}@Beanpublic GzipCompressingFilter gzipCompressingFilter() {GzipCompressingFilter filter = new GzipCompressingFilter();filter.setMinGzipSize(2048);List<String> mimeTypes = Arrays.asList("text/html", "text/xml", "text/plain", "text/css", "application/javascript", "application/json", "application/xml");filter.setMimeTypes(mimeTypes);return filter;}
}
2)、gzip壓縮
1.1接口使用-數據壓縮發送前端
@Autowiredprivate GzipUtils gzipUtils;@RequestMapping(value = "testGzip", method = RequestMethod.POST)public JSONBeansResponse testGzip(@RequestBody Map<String, String> map) throws IOException {if (null != map) {String sqlStr = map.get("paramStr");// 調用數據庫獲取數據Map<String, Object> resMap = testMapper.findInfo(sqlStr);String dataStr = JSONObject.toJSONString(resMap);// 開始壓縮數據byte[] compress1 = gzipUtils.compress(dataStr);String FileBuf = Base64.getEncoder().encodeToString(compress1);return new JSONBeansResponse<>(FileBuf);}return new JSONBeansResponse<>(new ArrayList<>(0));}
1.2 接口使用-數據解壓來自前端來的壓縮數據
@RequestMapping(value = "testUnGzip", method = RequestMethod.POST)public JSONBeansResponse testUnGzip(@RequestBody Map<String, String> map) throws IOException {if (null != map) {String dataStream = map.get("dataStream ");byte[] decode = Base64.getDecoder().decode(dataStream);byte[] compress1 = gzipUtils.uncompress(decode);String dataStr = new String(compress1);Map<String, Object> res = JSONObject.parseObject(dataStr, Map.class);return new JSONBeansResponse<>(res);}return new JSONBeansResponse<>(new ArrayList<>(0));}
遇到問題
解壓時候報錯:java.util.zip.ZipException: Not in GZIP format
解決方案:在轉換為字符串時,一定要使用ISO-8859-1這樣的單字節編碼
public R getLikeKeys(HttpServletRequest request, HttpServletResponse response, String data){String data = "xxxxxxxx"; // 前端傳來的數據String data3=new String(data.getBytes(), StandardCharsets.ISO_8859_1);}
1.3 GzipUtils工具類
package com.自己的包.util;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
/*** @program: tool_java* @description:* @author: sfp* @create: 2021-11-30 14:33**/
@Component
public class GzipUtils {/*** 壓縮** @param data 數據流* @return 壓縮數據流* @throws IOException 異常*/public byte[] compress(byte[] data) throws IOException {if (data == null || data.length == 0) {return null;}ByteArrayOutputStream out = new ByteArrayOutputStream();GZIPOutputStream gzip = new GZIPOutputStream(out);gzip.write(data);gzip.close();return out.toByteArray();}/*** 壓縮** @param str 需要壓縮數據信息* @return 壓縮數據流* @throws IOException 異常*/public byte[] compress(String str) throws IOException {if (str == null || str.length() == 0) {return null;}return compress(str.getBytes(StandardCharsets.UTF_8));}/*** 解壓** @param data 欲解壓數據流* @return 原數據流* @throws IOException 異常*/public byte[] uncompress(byte[] data) throws IOException {if (data == null || data.length == 0) {return data;}ByteArrayOutputStream out = new ByteArrayOutputStream();ByteArrayInputStream in = new ByteArrayInputStream(data);GZIPInputStream gunzip = new GZIPInputStream(in);byte[] buffer = new byte[1024];int n;while ((n = gunzip.read(buffer)) >= 0) {out.write(buffer, 0, n);}gunzip.close();in.close();return out.toByteArray();}/*** 解壓** @param str 欲解壓數據字符串* @return 原數據* @throws IOException 異常*/public String uncompress(String str) throws IOException {if (str == null || str.length() == 0) {return str;}byte[] data = uncompress(str.getBytes(StandardCharsets.ISO_8859_1));return new String(data);}
}
3)、前端壓縮數據
引入pako庫
首先,通過npm安裝pako庫:
npm install pako
如果你不使用npm,也可以通過CDN引入pako庫:
<script src="https://cdnjs.cloudflare.com/ajax/libs/pako/2.0.4/pako.min.js"></script>
1.2 實現GzipUtils類
然后,在JavaScript中實現GzipUtils類:
class GzipUtils {/*** 壓縮** @param {Uint8Array|ArrayBuffer} data 數據流* @return {Uint8Array} 壓縮數據流*/static compress(data) {if (!data || data.length === 0) {return null;}return pako.gzip(data);}/*** 壓縮** @param {string} str 需要壓縮數據信息* @return {Uint8Array} 壓縮數據流*/static compressString(str) {if (!str || str.length === 0) {return null;}const utf8Data = new TextEncoder().encode(str);return this.compress(utf8Data);}/*** 解壓** @param {Uint8Array|ArrayBuffer} data 欲解壓數據流* @return {Uint8Array} 原數據流*/static uncompress(data) {if (!data || data.length === 0) {return data;}return pako.ungzip(data);}/*** 解壓** @param {string} str 欲解壓數據字符串* @return {string} 原數據*/static uncompressString(str) {if (!str || str.length === 0) {return str;}const compressedData = new Uint8Array([...str].map(char => char.charCodeAt(0)));const uncompressedData = this.uncompress(compressedData);return new TextDecoder().decode(uncompressedData);}
}
1.3 前端使用示例
// 使用pako庫,確保pako庫已引入
// npm install pako
// 或者通過CDN引入 pako.min.js// 壓縮字符串
const originalString = "Hello, this is a string to be compressed.";
const compressedData = GzipUtils.compressString(originalString);
console.log("Compressed Data:", compressedData);// 解壓字符串
const decompressedString = GzipUtils.uncompressString(compressedData);
console.log("Decompressed String:", decompressedString);// 確保解壓后的字符串與原始字符串相同
console.assert(originalString === decompressedString, "Strings do not match!");
4)、zip壓縮方案
接口使用-數據壓縮發送前端
@Autowiredprivate ZipUtils zipUtils;@RequestMapping(value = "testzip", method = RequestMethod.POST)public JSONBeansResponse testzip(@RequestBody Map<String, String> map) throws IOException {String sqlStr = map.get("paramStr");List<Map<String, Object>> resMap = testMapper.findInfo(sqlStr);;String dataStr = JSONObject.toJSONString(resMap);// 開始壓縮數據byte[] compress1 = zipUtils.compress(dataStr);String FileBuf = Base64.getEncoder().encodeToString(compress1);// 開始解壓數據String s = zipUtils.uncompress(FileBuf);List<Map> arrayLists = JSONObject.parseArray(s, Map.class);return new JSONBeansResponse<>(arrayLists);}
接口使用-數據解壓來自前端來的壓縮數據
ZipUtils工具類
package com.自己的包.util;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
/**
* @program: tool_java
* @description: zip壓縮工具
* @author: sfp
* @create: 2021-12-01 14:11
**/
@Component
public class ZipUtils {
/** 壓縮* @param data 原數據流* @return 壓縮后的數據流* @throws IOException 異常*/public byte[] compress(byte[] data) throws IOException {if (data == null || data.length == 0) {return null;}ByteArrayOutputStream out = new ByteArrayOutputStream();ZipOutputStream gzip = new ZipOutputStream(out);gzip.putNextEntry(new ZipEntry("json"));gzip.write(data);gzip.close();return out.toByteArray();}/** 壓縮* @param str 原數據字符串* @return 壓縮后的數據流* @throws IOException 異常*/public byte[] compress(String str) throws IOException {if (str == null || str.length() == 0) {return null;}return compress(str.getBytes(StandardCharsets.UTF_8));}/** 解壓縮* @param data 壓縮后的數據流* @return 原數據的數據流* @throws IOException 異常*/public byte[] uncompress(byte[] data) throws IOException {if (data == null || data.length == 0) {return data;}ByteArrayOutputStream out = new ByteArrayOutputStream();ByteArrayInputStream in = new ByteArrayInputStream(data);ZipInputStream gunzip = new ZipInputStream(in);ZipEntry nextEntry = gunzip.getNextEntry();while (nextEntry != null) {final String fileName = nextEntry.getName();if (nextEntry.isDirectory()) {nextEntry = gunzip.getNextEntry();} else if (fileName.equals("json")) {byte[] buffer = new byte[1024];int n;while ((n = gunzip.read(buffer)) >= 0) {out.write(buffer, 0, n);}gunzip.close();in.close();return out.toByteArray();}}return out.toByteArray();}/** 解壓* @param str 壓縮后的base64流* @return 原數據字符串* @throws IOException 異常*/public String uncompress(String str) throws IOException {if (str == null || str.length() == 0) {return str;}byte[] data = uncompress(Base64.getDecoder().decode(str));return new String(data);}
}