PHP从URL下载大文件至服务器遇阻,寻求后台续传代码
解决PHP大文件后台下载(关闭浏览器也能完成)的问题
嘿,我来帮你搞定这个大文件下载的坑!你的代码之所以下载1GB文件到100MB就失败,核心问题出在file_get_contents上——它会把整个远程文件一次性加载到内存里,而PHP默认的内存限制一般也就128MB左右,内存撑爆了自然就断了。哪怕你开了ignore_user_abort(true),内存瓶颈没解决还是白搭。
下面给你一套专门针对大文件的后台下载方案,既能避免内存溢出,又能保证用户关闭浏览器后脚本继续跑完:
<?php // 开启后台执行:用户关闭浏览器后脚本继续运行 ignore_user_abort(true); // 取消脚本执行时间限制(大文件下载需要足够时间,也可以设成具体值比如86400=24小时) set_time_limit(0); // 替换成你的远程文件URL和本地保存路径 $remote_file_url = 'http://domain/id.mp4'; $local_save_path = 'file.mp4'; // 打开远程文件流(只读二进制模式) $remote_handle = fopen($remote_file_url, 'rb'); if (!$remote_handle) { die('无法连接到远程文件,请检查URL是否正确'); } // 打开本地文件流(追加二进制模式,中途中断后可以续传) $local_handle = fopen($local_save_path, 'ab'); if (!$local_handle) { fclose($remote_handle); die('无法创建/打开本地文件,请检查路径权限'); } // 每次读取的块大小,建议4MB-16MB,平衡内存占用和下载效率 $chunk_size = 4 * 1024 * 1024; // 4MB // 逐块读取远程文件并写入本地 while (!feof($remote_handle)) { // 读取一块数据 $chunk_data = fread($remote_handle, $chunk_size); if ($chunk_data === false) { break; // 读取失败就退出循环 } // 写入本地文件 fwrite($local_handle, $chunk_data); // 立即刷新缓冲区,确保数据写入磁盘(避免缓存丢失) fflush($local_handle); } // 关闭文件句柄,释放资源 fclose($remote_handle); fclose($local_handle); echo '大文件下载完成啦!'; ?>
关键细节说明:
- 文件流方式处理:用
fopen+fread+fwrite逐块操作,内存只占用你设置的chunk_size大小,再也不会因为大文件耗尽内存。 - 后台执行保障:
ignore_user_abort(true)确保用户关闭浏览器后,服务器端的脚本依然会继续执行完下载任务。 - 无时间限制:
set_time_limit(0)取消了PHP脚本的执行时间上限,不用担心大文件下载到一半超时。 - 断点友好:用
ab模式打开本地文件,如果下载中途意外中断,再次运行脚本可以从已经下载的位置继续(如果需要更完善的断点续传,可以额外加逻辑:先获取本地文件大小,然后给远程请求加Range头读取剩余部分)。
额外注意事项:
- 确保PHP配置里的
allow_url_fopen是开启状态(可以在php.ini里设置allow_url_fopen = On,或者代码里尝试ini_set('allow_url_fopen', 1))。 - 检查本地保存路径的读写权限,确保PHP进程能创建和写入文件。
- 如果服务器有
open_basedir限制,要把本地保存路径加到允许的目录里。 - 对于超大文件(比如几十GB),可以考虑加个日志功能,记录下载进度和可能的错误,方便排查问题。
内容的提问来源于stack exchange,提问作者Seeking help
相关产品推荐
相关产品推荐

