php写文件时网络中断本身不影响本地写入,因php不感知http连接状态;问题仅出现在写远程存储时可能导致数据不完整;应采用临时文件+原子重命名实现容错,并校验文件大小;大文件需分块上传+服务端校验续传;ignore_user_abort(true)不能替代断点续传。

PHP写文件中途网络中断会导致什么
PHP本身不感知HTTP连接是否断开,fwrite() 或 file_put_contents() 只管往本地磁盘或临时流里写。所谓“网络中断导致写失败”,实际是客户端断开后,服务端仍在执行——但若目标是写远程存储(如SFTP、WebDAV、分块上传API),问题才真正出现:部分数据已发、部分卡住、服务端无响应、文件不完整。
用临时文件 + 原子重命名实现基础容错
这是最轻量且可靠的本地写入兜底方式。核心是避免直接写目标路径,而是先写到同目录下的临时名(带唯一标识),成功后再rename()覆盖。
-
rename()在同一文件系统下是原子操作,不会出现“半覆盖”状态 - 临时文件名建议包含时间戳+随机字符串,例如
report_20240521_8a3f.tmp - 写完后务必用
is_file()+filesize()校验内容长度是否符合预期,再执行重命名 - 若进程被杀或崩溃,残留的
.tmp文件可由定时脚本清理(比如超过1小时未完成就删除)
大文件分块上传 + 服务端校验续传
真正需要“断点续传”的场景,基本都发生在HTTP上传(如用户上传视频)或向对象存储(如OSS、S3)推送大文件。PHP端不能只靠fopen()硬推,得配合协议支持:
- 客户端需用
fetch或XMLHttpRequest分块发送,每块附带Content-Range头 - 服务端接收时检查
$_SERVER['HTTP_CONTENT_RANGE'],解析已上传字节范围,用fopen($file, 'c')(追加模式)写入对应偏移 - 每次写入后调用
fseek()+fwrite()确保落位准确,再用fstat()验证当前文件大小 - 关键:上传前先发HEAD请求查服务端已存长度,决定从哪块开始——这步漏掉就不是续传,是重头覆盖
别把ignore_user_abort(true)当续传方案
这个函数只是让脚本在用户断开后继续执行,并不解决数据完整性问题。它常被误用为“断点续传开关”,但实际效果是:
立即学习“PHP免费学习笔记(深入)”;
- 如果网络中断时PHP正卡在
curl_exec()或fsockopen()等阻塞IO上,脚本可能仍会超时退出(取决于max_execution_time和socket timeout设置) - 即使跑完了,也无法知道客户端收到了多少字节,更无法恢复上传位置
- 更适合后台任务(如生成报表后发邮件),而非上传类交互流程
真要靠它兜底,必须搭配外部持久化记录:每次写入前更新数据库或Redis里的“已上传字节数”,重启后读取该值决定起点——但这已脱离PHP单脚本范畴,属于任务队列设计了。











