將遠端圖片下載儲存至本地伺服器,常用於內容遷移、圖床備份、編輯器圖片自動本地化。
Content-Type 推斷)<?php
function grabImage($url, $saveDir = '', $filename = '') {
if (empty($url)) return false;
// 1. 解析副檔名
$ext = '';
if (empty($filename)) {
$parsed = parse_url($url);
$path = $parsed['path'] ?? '';
$ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
if (!in_array($ext, ['jpg','jpeg','png','gif','webp','bmp'])) {
// 嘗試從 Content-Type 獲取
$headers = @get_headers($url, 1);
$ctype = $headers['Content-Type'] ?? '';
$extMap = [
'image/jpeg' => 'jpg', 'image/png' => 'png',
'image/gif' => 'gif', 'image/webp' => 'webp',
];
$ext = $extMap[$ctype] ?? 'jpg';
}
$filename = date('YmdHis') . '_' . mt_rand(1000,9999) . '.' . $ext;
}
// 2. 確保儲存目錄存在
$saveDir = $saveDir ?: sys_get_temp_dir();
if (!is_dir($saveDir)) {
mkdir($saveDir, 0755, true);
}
$filepath = rtrim($saveDir, '/') . '/' . $filename;
// 3. 下載(支援大檔案串流,避免記憶體爆炸)
$fpRemote = @fopen($url, 'rb');
if (!$fpRemote) return false;
$fpLocal = @fopen($filepath, 'wb');
if (!$fpLocal) {
fclose($fpRemote);
return false;
}
stream_copy_to_stream($fpRemote, $fpLocal); // 高效串流複製
fclose($fpRemote);
fclose($fpLocal);
// 4. 驗證檔案有效性
if (filesize($filepath) === 0) {
unlink($filepath);
return false;
}
return $filepath; // 或回傳相對 Web 根目錄的 URL
}
// 使用範例
$localPath = grabImage('https://example.com/photo.jpg', '/var/www/uploads');
if ($localPath) {
echo "下載成功:$localPath";
} else {
echo "下載失敗";
}
stream_copy_to_stream()Content-Type 推斷。uniqid() 或 UUID。mkdir(..., true) 遞迴建立,免去部署配置麻煩。CURLOPT_REFERER、User-Agent、Cookie 等 Header。Content-Type 為圖片類型,防止惡意檔案上傳。open_basedir、禁止執行權限、Nginx/Apache 禁用腳本解析。