原生PHP基于HTTP GET以1KB分块传输任意文件的哈希校验不匹配问题
代码异常原因与修正方案
核心问题定位
- 写入环节固定使用追加模式(
ab),若运行脚本前目标输出文件已存在旧残留内容,新写入的分块会直接拼接在旧内容后方,最终文件内容与源文件不一致,哈希值必然不匹配。 - 本地测试场景冗余引入base64编解码流程,每多一层转换就多一层出错风险:一旦编解码环节出现字符偏移、转义异常,就会破坏二进制内容的完整性。
- 循环读取逻辑缺少边界校验,当
fread读到文件末尾返回空内容时,虽然空字符串不会产生实际写入,但搭配追加模式使用时,会放大残留文件带来的异常。
修正后的可验证代码
<?php $input = "/home/lm1/Music/Ellise - Feeling Something Bad.mp3"; $output = pathinfo($input, PATHINFO_BASENAME); echo "\n> 源文件MD5: " . md5_file($input); // 提前清空目标文件,消除旧内容残留 file_put_contents($output, ''); $fp = fopen($input, 'rb'); if ($fp) { while (!feof($fp)) { $buffer = fread($fp, 1024); // 读到空内容直接跳出循环,避免无效操作 if ($buffer === false || $buffer === '') { break; } write($output, $buffer); } fclose($fp); echo "\n> 目标文件MD5: " . md5_file($output); echo "\n"; } function write($file, $buffer) { $fp = fopen($file, 'ab'); fwrite($fp, $buffer); fclose($fp); } ?>
适配HTTP GET分块传输的注意事项
- 所有文件读写操作必须指定二进制模式(
rb/wb/ab),避免跨平台环境下的换行符自动转换破坏二进制内容一致性。 - 分块通过GET参数传输时,必须对base64编码后的块内容做
urlencode处理,避免+、/、=等特殊字符被URL解析流程篡改,保证解码后的块内容与源文件块完全一致。 - 传输流程必须增加校验闭环:服务端提前提供源文件的整体哈希值,客户端拼接完所有块后先计算本地目标文件哈希,与源哈希比对;不一致时定位出错分块,单独重传对应分块即可。
- 1KB大小的原始数据块经base64编码后长度约为1.36KB,远低于常规服务器对GET请求的参数长度限制,不会触发协议层面的传输截断。
内容的提问来源于stack exchange,提问作者pQL7CmRP2i4
相关产品推荐
相关产品推荐

