採集器、發布接口常需將遠程文件(圖片、文檔等)下載至本地服務器。本文封裝一個健壯的 httpcopy() 函數:優先使用 cURL(性能更優、支持 HTTPS、超時控制),cURL 不可用時自動回退至 stream_context_create() + copy(),並自動創建目標目錄、處理 URL 編碼,適合生產環境直接使用。
function httpcopy($url, $file = '', $timeout = 60) {
// 1. 目標文件名處理
$file = empty($file) ? pathinfo($url, PATHINFO_BASENAME) : $file;
$dir = pathinfo($file, PATHINFO_DIRNAME);
if (!is_dir($dir)) {
@mkdir($dir, 0755, true); // 遞歸創建目錄
}
// 2. URL 空格編碼
$url = str_replace(' ', '%20', $url);
// 3. 優先使用 cURL
if (function_exists('curl_init')) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 支持 301/302 重定向
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 忽略 SSL 證書驗證(按需開啟)
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$content = curl_exec($ch);
$errno = curl_errno($ch);
$error = curl_error($ch);
curl_close($ch);
if ($errno === 0 && @file_put_contents($file, $content) !== false) {
return $file;
}
// cURL 失敗時不直接返回 false,嘗試回退方案
}
// 4. 回退:stream_context + copy()
$opts = [
'http' => [
'method' => 'GET',
'header' => '',
'timeout' => $timeout,
'follow_location' => 1,
'ignore_errors' => true,
],
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
]
];
$context = stream_context_create($opts);
if (@copy($url, $file, $context)) {
return $file;
}
return false;
}
// 下載百度 Logo 到當前目錄
$result = httpcopy('https://www.baidu.com/img/baidu_sylogo1.gif');
if ($result) {
echo "下載成功:$result";
} else {
echo "下載失敗";
}
// 指定保存路徑
httpcopy('https://example.com/file.pdf', '/var/www/uploads/docs/manual.pdf', 120);
| 特性 | 實現細節 |
|---|---|
| 目錄自動創建 | pathinfo($file, PATHINFO_DIRNAME) + mkdir(..., true) |
| URL 編碼 | str_replace(' ', '%20') 處理含空格 URL |
| cURL 優先 | 測試表明 cURL 響應更快、內存佔用更低 |
| 超時控制 | 參數 $timeout 同時應用於 cURL 與 stream context |
| HTTPS 支持 | 關閉 SSL 驗證避免自簽證書失敗,生產環境建議配置 CA 證書 |
| 重定向跟隨 | CURLOPT_FOLLOWLOCATION / follow_location |
| 錯誤靜默 | @ 抑制警告,統一返回 false 供上層處理 |
User-Agent、Referer 模擬瀏覽器行為。CURLOPT_WRITEFUNCTION 寫入文件流,避免內存峰值。Content-Type 檢查、文件大小限制、MD5 校驗。此函數經多個採集項目驗證,穩定可靠,可直接納入通用工具庫。