7.1 KiB
7.1 KiB
大屏保存 Gzip 压缩 - 后端处理示例
前端实现说明
当前端保存数据超过 100KB 时,会自动启用 Gzip 压缩,请求格式如下:
压缩数据请求格式
{
"compressed": true,
"content": "<base64 编码的 Gzip 压缩数据>"
}
请求头
Content-Encoding: gzip
X-Data-Original-Size: 123456
X-Data-Compressed-Size: 34567
Authorization: <token>
Java Spring Boot 后端处理示例
Controller 层
@PostMapping("/reportDashboard")
public Result saveDashboard(@RequestBody Map<String, Object> 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<String, Object> params) {
// 根据实际业务对象转换
DashboardData data = new DashboardData();
data.setReportCode((String) params.get("reportCode"));
// ... 其他字段转换
return data;
}
实体类示例
@Data
public class DashboardData {
private String reportCode;
private DashboardInfo dashboard;
private List<WidgetInfo> 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 后端处理示例
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 处理示例
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 反向代理,需要调整请求体大小限制:
server {
# ... 其他配置
# 允许最大请求体大小(根据实际需求调整)
client_max_body_size 50M;
# 超时时间设置
client_body_timeout 120s;
proxy_read_timeout 120s;
}
测试验证
使用 curl 测试压缩数据
# 构造测试数据
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"
注意事项
- 字符编码:确保前后端都使用 UTF-8 编码
- Base64 安全:考虑使用 URL安全的 Base64 编码变体
- 错误处理:解压失败时返回明确的错误信息
- 日志记录:记录压缩/解压的大小信息便于排查问题
- 性能监控:监控解压耗时,避免性能瓶颈