You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 07:17:36