# 大屏保存 Gzip 压缩 - 后端处理示例 ## 前端实现说明 当前端保存数据超过 100KB 时,会自动启用 Gzip 压缩,请求格式如下: ### 压缩数据请求格式 ```json { "compressed": true, "content": "" } ``` ### 请求头 ``` Content-Encoding: gzip X-Data-Original-Size: 123456 X-Data-Compressed-Size: 34567 Authorization: ``` ## Java Spring Boot 后端处理示例 ### Controller 层 ```java @PostMapping("/reportDashboard") public Result saveDashboard(@RequestBody Map params, @RequestHeader(value = "Content-Encoding", required = false) String encoding, @RequestHeader(value = "X-Data-Original-Size", required = false) Integer originalSize, @RequestHeader(value = "X-Data-Compressed-Size", required = false) Integer compressedSize) { try { DashboardData dashboardData; // 判断是否为压缩数据 if ("gzip".equalsIgnoreCase(encoding) && params.containsKey("compressed")) { Boolean isCompressed = (Boolean) params.get("compressed"); if (isCompressed != null && isCompressed) { String compressedContent = (String) params.get("content"); // 解压数据 dashboardData = gzipDecompress(compressedContent); log.info("接收压缩数据:原始 {} KB -> 压缩后 {} KB", originalSize != null ? originalSize / 1024.0 : 0, compressedSize != null ? compressedSize / 1024.0 : 0); } else { // 未压缩数据直接转换 dashboardData = convertToDashboard(params); } } else { // 普通数据直接处理 dashboardData = convertToDashboard(params); } // 保存业务逻辑 return dashboardService.save(dashboardData); } catch (Exception e) { log.error("保存大屏失败", e); return Result.error("保存失败:" + e.getMessage()); } } /** * Gzip 解压工具方法 */ private DashboardData gzipDecompress(String base64Data) throws IOException { // Base64 解码 byte[] compressed = Base64.getDecoder().decode(base64Data); // Gzip 解压 ByteArrayOutputStream out = new ByteArrayOutputStream(); try (GZIPInputStream in = new GZIPInputStream(new ByteArrayInputStream(compressed))) { byte[] buffer = new byte[1024]; int len; while ((len = in.read(buffer)) > 0) { out.write(buffer, 0, len); } } // 转回字符串 String json = out.toString("UTF-8"); // 解析为对象 return JSON.parseObject(json, DashboardData.class); } /** * 转换为 Dashboard 对象 */ private DashboardData convertToDashboard(Map params) { // 根据实际业务对象转换 DashboardData data = new DashboardData(); data.setReportCode((String) params.get("reportCode")); // ... 其他字段转换 return data; } ``` ### 实体类示例 ```java @Data public class DashboardData { private String reportCode; private DashboardInfo dashboard; private List widgets; @Data public static class DashboardInfo { private String title; private String width; private String height; private String backgroundColor; private String backgroundImage; private Integer refreshSeconds; } @Data public static class WidgetInfo { private String type; private WidgetValue value; @Data public static class WidgetValue { private SetupInfo setup; private PositionInfo position; private DataInfo data; } } } ``` ## Node.js 后端处理示例 ```javascript const zlib = require('zlib'); const util = require('util'); const gunzip = util.promisify(zlib.gunzip); app.post('/reportDashboard', async (req, res) => { try { let dashboardData; const encoding = req.headers['content-encoding']; if (encoding === 'gzip' && req.body.compressed) { // 解压数据 const compressedBuffer = Buffer.from(req.body.content, 'base64'); const uncompressedBuffer = await gunzip(compressedBuffer); const jsonString = uncompressedBuffer.toString('utf8'); dashboardData = JSON.parse(jsonString); console.log(`接收压缩数据:原始 ${req.headers['x-data-original-size'] / 1024} KB -> 压缩后 ${req.headers['x-data-compressed-size'] / 1024} KB`); } else { // 普通数据 dashboardData = req.body; } // 保存业务逻辑 await saveDashboard(dashboardData); res.json({ code: '200', message: '保存成功' }); } catch (error) { console.error('保存失败:', error); res.status(500).json({ code: '500', message: '保存失败' }); } }); ``` ## Python Flask 处理示例 ```python import gzip import base64 import json from flask import request, jsonify @app.route('/reportDashboard', methods=['POST']) def save_dashboard(): try: data = request.get_json() encoding = request.headers.get('Content-Encoding') if encoding == 'gzip' and data.get('compressed'): # 解压数据 compressed_data = base64.b64decode(data['content']) decompressed_data = gzip.decompress(compressed_data) dashboard_data = json.loads(decompressed_data) original_size = request.headers.get('X-Data-Original-Size') compressed_size = request.headers.get('X-Data-Compressed-Size') print(f"接收压缩数据:原始 {int(original_size)/1024:.2f} KB -> 压缩后 {int(compressed_size)/1024:.2f} KB") else: dashboard_data = data # 保存业务逻辑 result = save_to_database(dashboard_data) return jsonify({'code': '200', 'message': '保存成功'}) except Exception as e: print(f"保存失败:{e}") return jsonify({'code': '500', 'message': '保存失败'}), 500 ``` ## Nginx 配置建议 如果使用了 Nginx 反向代理,需要调整请求体大小限制: ```nginx server { # ... 其他配置 # 允许最大请求体大小(根据实际需求调整) client_max_body_size 50M; # 超时时间设置 client_body_timeout 120s; proxy_read_timeout 120s; } ``` ## 测试验证 ### 使用 curl 测试压缩数据 ```bash # 构造测试数据 DATA='{"compressed":true,"content":"H4sIAAAAAAAAA..."}' # 发送请求 curl -X POST http://localhost:8080/reportDashboard \ -H "Content-Type: application/json" \ -H "Content-Encoding: gzip" \ -H "X-Data-Original-Size: 123456" \ -H "X-Data-Compressed-Size: 34567" \ -d "$DATA" ``` ## 注意事项 1. **字符编码**:确保前后端都使用 UTF-8 编码 2. **Base64 安全**:考虑使用 URL安全的 Base64 编码变体 3. **错误处理**:解压失败时返回明确的错误信息 4. **日志记录**:记录压缩/解压的大小信息便于排查问题 5. **性能监控**:监控解压耗时,避免性能瓶颈