C语言实现的小型Web服务器读取gzip压缩文件报错如何解决
问题原因
- 核心问题是原
readFile函数仅返回文件内容指针,没有将文件大小fsize显式传递给上层调用逻辑:gzip是二进制格式,文件内部包含大量0x00字节,C语言中字符串以0x00作为结束标识,上层如果沿用读取文本时的习惯,用strlen(data)计算需要发送的内容长度,会在遇到第一个0x00字节时就提前截断,导致实际发给浏览器的gzip数据不完整。 - 你设置的
Content-Length响应头大概率使用了strlen(data)的错误值,而非实际的gzip文件大小,浏览器收到长度不足的gzip流无法完成解码,就会出现乱码或者ERR_CONTENT_DECODING_FAILED错误。 - 次要问题:原函数中
fread(data, fsize, 1, file)的写法不易判断读取是否完整,若文件读取过程中出现异常,你无法感知到读取字节数不足的情况。
解决方法
- 修改
readFile函数,增加输出参数传递文件大小,参考修改后的代码:
// 新增outFsize输出参数,用于返回读取到的文件字节数 char* readFile(char* path, long* outFsize) { *outFsize = 0; FILE* file = fopen(path, "rb"); if(file == NULL) return NULL; fseek(file, 0, SEEK_END); long fsize = ftell(file); fseek(file, 0, SEEK_SET); // 二进制文件不需要额外预留字符串结束符位置,用malloc替代calloc性能更好 char* data = (char*)malloc(fsize); if (data == NULL) { fclose(file); return NULL; } // 调整fread参数,按单字节为单位读取,方便判断实际读取字节数 size_t readBytes = fread(data, 1, fsize, file); fclose(file); if (readBytes != fsize) { free(data); return NULL; } *outFsize = fsize; return data; }
- 上层调用该函数时,使用输出的
outFsize作为Content-Length响应头的取值,同时发送响应体时也按照outFsize的长度发送,禁止使用strlen计算内容长度。 - 可选校验:可以提前校验本地压缩后的gzip文件完整性,排除文件本身损坏的可能性。
内容的提问来源于stack exchange,提问作者rayanJ
相关产品推荐
相关产品推荐

