基于PHP/AJAX从URL批量下载图片的问题与实现需求
问题解决:修复图片损坏+AJAX分批下载
一、修复服务器端图片下载损坏问题
你的curl代码缺少HTTPS验证处理、请求头模拟,且未捕获错误,这是导致图片损坏的核心原因。以下是修复后的代码:
<?php $images = [ 'http://ensemblepakistan.com/wp-content/uploads/2018/06/11.jpg', 'https://ensemblepakistan.com/wp-content/uploads/2018/08/SHK-242-3.jpg', 'https://ensemblepakistan.com/wp-content/uploads/2018/08/SHK-242-1.jpg', 'https://ensemblepakistan.com/wp-content/uploads/2018/08/SHK-242-2.jpg', 'https://ensemblepakistan.com/wp-content/uploads/2018/08/SHBK-258-3.jpg', 'https://ensemblepakistan.com/wp-content/uploads/2018/08/SHBK-258-2.jpg', 'https://ensemblepakistan.com/wp-content/uploads/2018/08/SHBK-258-1.jpg', 'https://ensemblepakistan.com/wp-content/uploads/2018/10/SHBK-313-3-min.jpg' ]; $saveDir = $_SERVER['DOCUMENT_ROOT'] . '/test/'; // 确保保存目录存在 if (!is_dir($saveDir)) { mkdir($saveDir, 0755, true); } foreach ($images as $image) { $name = basename($image); // 处理重名文件,避免覆盖 $savePath = $saveDir . $name; $counter = 1; while (file_exists($savePath)) { $ext = pathinfo($name, PATHINFO_EXTENSION); $baseName = pathinfo($name, PATHINFO_FILENAME); $savePath = $saveDir . "{$baseName}_{$counter}.{$ext}"; $counter++; } $ch = curl_init($image); $fp = fopen($savePath, 'wb'); curl_setopt_array($ch, [ CURLOPT_FILE => $fp, CURLOPT_HEADER => false, CURLOPT_FOLLOWLOCATION => true, // 跟随重定向 CURLOPT_SSL_VERIFYPEER => false, // 跳过SSL证书验证(按需开启) CURLOPT_SSL_VERIFYHOST => false, CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36', // 模拟浏览器请求 CURLOPT_TIMEOUT => 30 // 设置超时时间 ]); $result = curl_exec($ch); if (!$result) { // 捕获curl错误 error_log("下载失败:{$image},错误信息:" . curl_error($ch)); fclose($fp); unlink($savePath); // 删除空文件 curl_close($ch); continue; } // 检查HTTP响应码是否为200 $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($httpCode !== 200) { error_log("下载失败:{$image},HTTP状态码:{$httpCode}"); fclose($fp); unlink($savePath); curl_close($ch); continue; } curl_close($ch); fclose($fp); }
关键修复点:
- 添加
CURLOPT_FOLLOWLOCATION处理重定向,部分图片URL可能存在跳转 - 跳过SSL证书验证(针对HTTPS站点,若服务器信任证书可移除)
- 模拟浏览器
User-Agent,避免被目标服务器拦截 - 处理重名文件,防止覆盖已有图片
- 捕获curl错误和HTTP状态码,及时清理损坏文件
二、实现AJAX分批下载
需要前端JS和后端接口配合,每次请求下载指定数量的图片,完成后自动发起下一批请求。
1. 后端接口(batch-download.php)
<?php $images = [ // 你的图片URL数组 'http://ensemblepakistan.com/wp-content/uploads/2018/06/11.jpg', 'https://ensemblepakistan.com/wp-content/uploads/2018/08/SHK-242-3.jpg', // ... 其他图片URL ]; $start = isset($_POST['start']) ? (int)$_POST['start'] : 0; $limit = isset($_POST['limit']) ? (int)$_POST['limit'] : 20; $batchImages = array_slice($images, $start, $limit); $successCount = 0; $errorUrls = []; $saveDir = $_SERVER['DOCUMENT_ROOT'] . '/test/'; if (!is_dir($saveDir)) { mkdir($saveDir, 0755, true); } foreach ($batchImages as $image) { $name = basename($image); $savePath = $saveDir . $name; $counter = 1; while (file_exists($savePath)) { $ext = pathinfo($name, PATHINFO_EXTENSION); $baseName = pathinfo($name, PATHINFO_FILENAME); $savePath = $saveDir . "{$baseName}_{$counter}.{$ext}"; $counter++; } $ch = curl_init($image); $fp = fopen($savePath, 'wb'); curl_setopt_array($ch, [ CURLOPT_FILE => $fp, CURLOPT_HEADER => false, CURLOPT_FOLLOWLOCATION => true, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36', CURLOPT_TIMEOUT => 30 ]); $result = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); fclose($fp); if ($result && $httpCode === 200) { $successCount++; } else { $errorUrls[] = $image; unlink($savePath); } } echo json_encode([ 'success' => true, 'successCount' => $successCount, 'errorUrls' => $errorUrls, 'totalImages' => count($images), 'currentStart' => $start, 'limit' => $limit ]);
2. 前端AJAX代码(HTML页面)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>分批图片下载</title> </head> <body> <div id="progress"></div> <script> const batchSize = 20; // 每次下载20张 let currentStart = 0; const totalImages = 8; // 替换为实际图片总数 function downloadBatch() { if (currentStart >= totalImages) { document.getElementById('progress').textContent = '所有图片下载完成!'; return; } fetch('batch-download.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: `start=${currentStart}&limit=${batchSize}` }) .then(response => response.json()) .then(data => { const progressText = `已完成 ${Math.min(currentStart + batchSize, totalImages)}/${totalImages} 张图片,成功下载 ${data.successCount} 张,失败 ${data.errorUrls.length} 张`; document.getElementById('progress').textContent = progressText; currentStart += batchSize; // 延迟1秒发起下一批请求(避免服务器压力过大) setTimeout(downloadBatch, 1000); }) .catch(error => { document.getElementById('progress').textContent = `请求失败:${error.message}`; }); } // 启动下载 downloadBatch(); </script> </body> </html>
分批下载逻辑说明:
- 前端维护
currentStart变量,标记当前批次的起始索引 - 每次请求后端接口,传入
start和limit参数,后端截取对应批次的图片数组进行下载 - 后端返回下载结果后,前端更新进度,并自动发起下一批请求,直到所有图片处理完成
- 添加延迟请求,避免短时间内大量请求导致服务器负载过高
内容的提问来源于stack exchange,提问作者Sahibzada Jawad
相关产品推荐
相关产品推荐

