php处理大文件读取中断并实现断点续传有五种方法:一、fopen+fseek分块读取与进度保存;二、curl多段并发+校验合并;三、自定义stream_wrapper注册可恢复流协议;四、session+token管理http层传输状态;五、x-sendfile/x-accel-redirect交由web服务器处理断点。

如果PHP在读取大文件过程中因网络波动、超时或客户端断开连接导致读取中断,则无法完整获取文件内容。以下是处理此类中断并实现断点续传的多种方法:
一、使用fopen配合fseek实现分块读取与断点恢复
该方法通过记录已读取的字节偏移量,在下次请求时从该位置继续读取,避免重复传输和内存溢出。
1、在服务端保存当前读取进度至临时文件或数据库,例如写入offset.txt记录已传输字节数。
2、客户端发起续传请求时,在HTTP头中携带Range字段,如Range: bytes=1024-。
立即学习“PHP免费学习笔记(深入)”;
3、PHP脚本解析$_SERVER['HTTP_RANGE'],提取起始偏移量,并用fseek($fp, $start_offset)定位文件指针。
4、调用fread($fp, $chunk_size)分块读取剩余内容,每次读取后更新offset.txt中的值。
5、响应时设置HTTP状态码为206 Partial Content,并添加Content-Range头,例如Content-Range: bytes 1024-9999/10000。
二、基于cURL多段并发请求与本地校验合并
将大文件切分为固定大小的数据块,分别发起独立HTTP请求,各块成功后写入对应临时文件,最后按序合并。
1、服务端提供接口支持按块索引返回数据,例如/api/file/chunk?file_id=abc&index=2。
2、客户端预先计算总块数及每块起止范围,生成任务队列。
3、使用cURL_multi_init并发请求多个块,每个请求设置CURLOPT_TIMEOUT为30秒防止长期挂起。
4、对每个返回的块数据进行MD5校验,若失败则重试三次,仍失败则标记该块为待重传。
5、所有块下载完成后,按index顺序cat或file_put_contents追加写入目标文件。
三、利用stream_wrapper_register注册自定义流处理器
通过注册可中断、可恢复的流协议,使fopen/fread等原生函数自动支持断点逻辑,无需修改业务代码。
1、定义类MyFileStreamWrapper实现StreamWrapper接口,重写stream_open、stream_read等方法。
2、在stream_open中检查是否存在同名.offset文件,若有则读取上次终止位置并设置内部$position变量。
3、stream_read中根据当前$position读取指定长度数据,并实时更新.offset文件内容。
4、调用stream_wrapper_register('resumable', 'MyFileStreamWrapper')注册协议。
5、后续使用fopen('resumable://path/to/file.zip', 'r')即可透明启用断点续传功能。
四、结合session与临时存储实现HTTP层断点控制
利用PHP session保存传输上下文,在请求中断后通过唯一token重新关联会话状态,恢复传输流程。
1、首次请求时生成UUID作为transfer_token,并存入$_SESSION["{$token}_status"] = ['offset' => 0, 'total' => $size]。
2、客户端在每次请求Header中携带Transfer-Token: abc-def-ghi。
3、PHP脚本通过$_SERVER['HTTP_TRANSFER_TOKEN']获取token,从session读取当前offset值。
4、读取文件时跳过已传部分,使用fpassthru输出剩余内容,并在每次输出后更新session中的offset。
5、响应头中返回X-Resume-Offset: 12345,供客户端判断是否需发起下一段请求。
五、使用X-Sendfile或X-Accel-Redirect配合Nginx/Apache断点支持
将实际文件传输交由Web服务器处理,PHP仅负责权限校验与Range头解析,大幅提升稳定性和性能。
1、确保Nginx启用sendfile和add_header Accept-Ranges bytes指令,Apache启用mod_headers与mod_xsendfile模块。
2、PHP验证用户权限后,不直接输出文件内容,而是设置header('X-Accel-Redirect: /protected/file.zip')。
3、Nginx接收到X-Accel-Redirect后,自动识别Range头并执行断点传输,同时忽略PHP进程中断影响。
4、若需记录进度,可在location块中配置log_format包含$http_range变量,写入访问日志供分析。
5、客户端收到206响应且Content-Range正确,说明Web服务器已接管并完成断点逻辑。











