zlib是否支持流式解压?分段传输的gzip文件解压问询
zlib流式解压支持说明及代码问题分析
zlib完全支持流式解压,gzip格式本身也设计为可流式处理——哪怕gzip数据被拆分成多个TCP段传输,你完全可以在收到每一段数据后立即调用zlib的解压接口,逐步获取原始数据,根本不需要等待完整文件。你的测试结论有误,问题出在代码实现上。
你的代码核心问题:
- 循环逻辑错误:当前循环条件
do { ... } while (0 == z_stream_ptr->avail_out);仅在输出缓冲区被填满时才继续处理。如果当前输入段的数据不足以填满输出缓冲区,循环会直接终止,导致这段输入数据没被完全处理,自然得不到对应解压结果。正确逻辑应该是持续调用inflate,直到当前输入段的所有数据都处理完毕(即z_stream_ptr->avail_in == 0)。 - 错误处理不严谨:当
inflate返回Z_DATA_ERROR等致命错误时,代码仅打印日志却不终止流程。比如收到第一个TCP段时,可能只有gzip头部数据,此时inflate可能返回Z_OK但无输出,后续错误未处理会导致流程混乱。 - 未正确识别
inflate返回状态:inflate返回Z_OK表示还有数据待处理,Z_STREAM_END才代表整个压缩流结束。你的代码未区分这些状态,导致分段处理时无法正确推进。
你的原始代码:
int http_content_decompress_write_zlib(struct http_content_decompress *decompress, const char *indata, size_t indata_len, char **outdata, size_t *outdata_len) { z_stream *z_stream_ptr = decompress->z_stream_ptr; z_stream_ptr->avail_in = (unsigned int)indata_len; z_stream_ptr->next_in = (unsigned char *)indata; *outdata = NULL; *outdata_len = 0; int ret = 0; do { z_stream_ptr->avail_out = (unsigned int)decompress->buffer_size; z_stream_ptr->next_out = (unsigned char *)decompress->buffer; ret = inflate(z_stream_ptr, Z_NO_FLUSH); if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR) { printf("error msg:%s\n", z_stream_ptr->msg); //(void)inflateEnd(z_stream_ptr); //return -1; } size_t have = decompress->buffer_size - z_stream_ptr->avail_out; if (have > 0) { if (NULL == *outdata) { http_decoder_log(DEBUG, "%s alloc outbuffer %zu bytes", http_content_encoding_int2str(decompress->encoding), have); *outdata = safe_dup(decompress->buffer, have); *outdata_len = have; } else { http_decoder_log(DEBUG, "%s realloc outbuffer %zu bytes", http_content_encoding_int2str(decompress->encoding), *outdata_len + have + 1); *outdata = REALLOC(char, *outdata, *outdata_len + have + 1); memcpy(*outdata + *outdata_len, decompress->buffer, have); *outdata_len = *outdata_len + have; memset(*outdata + *outdata_len, 0, 1); } } else { } } while (0 == z_stream_ptr->avail_out); return 0; }
修正思路:
- 把循环条件改为
while (z_stream_ptr->avail_in > 0 || ret == Z_OK),确保当前输入段的所有数据都被处理完。 - 遇到致命错误时立即返回错误码,避免后续无效处理。
- 区分
Z_OK(仍有数据待处理)和Z_STREAM_END(压缩流结束)的状态,流式处理不需要等到Z_STREAM_END才返回结果。
内容的提问来源于stack exchange,提问作者luis
相关产品推荐
相关产品推荐

