基于QWebChannel实现Qt与JavaScript间zlib压缩JSON数据交互
解决QWebChannel传输压缩数据后pako解压报错的问题
可能的原因及对应解决方法
1. 压缩格式与pako解压参数不匹配
Qt的QByteArray::compress()默认生成带zlib头和校验位的压缩数据,pako的inflate()默认支持这种格式;但如果Qt端使用了原始deflate压缩(无zlib头),则需要给pako传入{raw: true}参数:
- Qt端原始deflate示例(直接调用zlib库):
QByteArray rawDeflate(const QByteArray& data) { z_stream strm; strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; deflateInit(&strm, Z_DEFAULT_COMPRESSION); strm.next_in = (Bytef*)data.constData(); strm.avail_in = data.size(); QByteArray result; do { char outBuffer[1024]; strm.next_out = (Bytef*)outBuffer; strm.avail_out = sizeof(outBuffer); deflate(&strm, Z_FINISH); result.append(outBuffer, sizeof(outBuffer) - strm.avail_out); } while (strm.avail_out == 0); deflateEnd(&strm); return result; } - 对应JS端解压代码:
const uint8Array = ...; // 从传输数据转换而来的二进制数组 const uncompressed = pako.inflate(uint8Array, { raw: true });
如果Qt用的是标准QByteArray::compress(),则直接用pako.inflate(uint8Array)即可。
2. 传输过程中二进制数据损坏
QWebChannel在传输二进制数据时,若直接以字符串形式传递,可能因编码(如UTF-8)导致二进制字节丢失或篡改。解决方法是将压缩数据转成Base64编码后传输:
- Qt端转换代码:
QByteArray rawData = ...; // 原始大数据 QByteArray compressed = rawData.compress(); QString compressedBase64 = compressed.toBase64(); // 通过QWebChannel传递compressedBase64字符串 - JS端解码并解压:
// 接收Qt传来的base64字符串 function handleCompressedData(compressedBase64) { // 解码Base64为Uint8Array const binaryStr = atob(compressedBase64); const uint8Array = new Uint8Array(binaryStr.length); for (let i = 0; i < binaryStr.length; i++) { uint8Array[i] = binaryStr.charCodeAt(i); } // 解压数据 try { const uncompressedArray = pako.inflate(uint8Array); // 将Uint8Array转换为原始数据格式(如Float64Array,根据你的数据类型) const data = new Float64Array(uncompressedArray.buffer); // 传给PlotlyJS使用 Plotly.newPlot('graph', [{x: [...], y: Array.from(data)}]); } catch (e) { console.error('解压失败:', e); } }
3. 验证压缩数据的完整性
在Qt端先本地验证压缩结果是否正确,排除压缩本身的问题:
QByteArray rawData = ...; QByteArray compressed = rawData.compress(); QByteArray uncompressed = compressed.uncompress(); if (uncompressed == rawData) { // 压缩正常,问题出在传输或JS端 } else { // Qt端压缩逻辑有误,检查数据或压缩参数 }
4. 检查是否误用gzip格式
如果Qt端意外使用了gzip格式(而非zlib),则需要用pako.inflateGzip()解压:
const uncompressed = pako.inflateGzip(uint8Array);
内容的提问来源于stack exchange,提问作者Peter Devenyi
相关产品推荐
相关产品推荐

