PHP copy()仅复制图片一半问题求助:如何完整复制远程图片?
远程图片复制经常不完整,求解决办法!
最近碰到个头疼的小问题:我尝试把远程图片https://trevim.pt/header-4/复制到目标路径https://trevim.pt/anuncios/header.png,脚本执行后每次都显示‘File copied successfully’,但有时候图片只复制了上半部分。这图片才22.6KB,完全不算大文件啊,这情况正常吗?有没有办法确保每次都能完整复制?
我的代码是这样的:
foreach($to_activate as $data_row) { $template_id = $data_row['template_id']; $img_url = $data_row['img_url']; $template = mysqli_query($conn, "SELECT name FROM `wp_ad_templates` WHERE id = '$template_id' limit 1")->fetch_object()->name; $dst = "../" . $template . ".png"; if(!@copy($img_url, $dst)) { $errors= error_get_last(); echo "COPY ERROR: ".$errors['type']; echo "<br>".$errors['message']."<br><br>"; } else { echo "File copied from remote!"; } }
另外我找过类似问题,有人说用exec()能解决,但我这边因为安全原因exec()被禁用了,试了直接报错:COPY ERROR: 2 exec() has been disabled for security reasons,所以这个方案走不通。
给你几个靠谱的解决思路:
- 改用cURL手动控制下载流程
copy()函数依赖PHP的流包装器,遇到网络波动或者服务器端的分块响应时,很容易出现下载不完整的情况。cURL能提供更精准的控制,比如设置超时、处理重定向、验证文件大小。试试这个封装好的函数:
function copyRemoteFile($url, $dst) { $ch = curl_init($url); $fp = fopen($dst, 'wb'); // 关键配置,确保下载完整 curl_setopt($ch, CURLOPT_FILE, $fp); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 自动处理3xx重定向 curl_setopt($ch, CURLOPT_TIMEOUT, 30); // 防止长时间卡住 curl_setopt($ch, CURLOPT_FAILONERROR, true); // HTTP错误直接终止 $downloadSuccess = curl_exec($ch); // 验证文件大小是否匹配远程资源 if ($downloadSuccess) { $remoteFileSize = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD); $localFileSize = filesize($dst); // 如果大小不匹配,删除损坏文件并返回失败 if ($remoteFileSize != $localFileSize) { fclose($fp); unlink($dst); curl_close($ch); return false; } } fclose($fp); curl_close($ch); return $downloadSuccess; } // 替换原来的copy调用 foreach($to_activate as $data_row) { $template_id = $data_row['template_id']; $img_url = $data_row['img_url']; $template = mysqli_query($conn, "SELECT name FROM `wp_ad_templates` WHERE id = '$template_id' limit 1")->fetch_object()->name; $dst = "../" . $template . ".png"; if(!copyRemoteFile($img_url, $dst)) { $errors= error_get_last(); echo "COPY ERROR: ".$errors['type']; echo "<br>".$errors['message']."<br><br>"; } else { echo "File copied from remote!"; } }
增加重试机制
可以在copyRemoteFile函数里加个重试逻辑,比如下载失败或者文件不完整时,最多重试2次,避免单次网络波动导致的问题。检查PHP配置
确保allow_url_fopen在php.ini里是开启的(不过即使开启,copy()的稳定性还是不如cURL)。
内容的提问来源于stack exchange,提问作者Henrique Saias
相关产品推荐
相关产品推荐

