首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 遠端下載圖片至本地完整實作指南

     編輯:PHP 相關知識

PHP 遠端下載圖片至本地完整實作指南

在專案開發中,常需從外部 URL 抓取圖片並儲存至伺服器。本文提供一個健壯、可復用的 PHP 函式 getImage(),支援 cURL 與 readfile() 兩種下載方式、自動建立目錄、副檔名驗證、錯誤代碼回傳,並附上完整呼叫範例。

核心函式:getImage()

<?php
/**
 * 遠端下載圖片至本地
 *
 * @param string $url          圖片 URL
 * @param string $save_dir     儲存目錄(預設 ./)
 * @param string $filename     儲存檔名(預設取 URL 尾部副檔名 + 時間戳)
 * @param int    $type         下載方式:0=readfile(預設), 1=cURL
 * @return array               ['file_name', 'save_path', 'error']
 */
function getImage($url, $save_dir = '', $filename = '', $type = 0) {
    // 參數檢核
    if (trim($url) === '') {
        return ['file_name' => '', 'save_path' => '', 'error' => 1]; // URL 為空
    }
    if (trim($save_dir) === '') {
        $save_dir = './';
    }
    // 確保目錄以 / 結尾
    if (substr($save_dir, -1) !== '/') {
        $save_dir .= '/';
    }

    // 自動產生檔名
    if (trim($filename) === '') {
        $ext = strrchr($url, '.');
        // 僅允許常見圖片副檔名
        if (!in_array(strtolower($ext), ['.gif', '.jpg', '.jpeg', '.png', '.webp'], true)) {
            return ['file_name' => '', 'save_path' => '', 'error' => 3]; // 副檔名不支援
        }
        $filename = time() . $ext;
    }

    // 建立目錄(遞迴、權限 0777)
    if (!file_exists($save_dir) && !mkdir($save_dir, 0777, true)) {
        return ['file_name' => '', 'save_path' => '', 'error' => 5]; // 目錄建立失敗
    }

    // 取得遠端檔案內容
    $img = '';
    if ($type === 1) {
        // cURL 方式(支援 HTTPS、可設定逾時)
        $ch = curl_init();
        $timeout = 10;
        curl_setopt_array($ch, [
            CURLOPT_URL            => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_CONNECTTIMEOUT => $timeout,
            CURLOPT_FOLLOWLOCATION => true, // 支援重導向
            CURLOPT_SSL_VERIFYPEER => false, // 正式環境建議設 true 並配置 CA 憑證
        ]);
        $img = curl_exec($ch);
        if (curl_errno($ch)) {
            curl_close($ch);
            return ['file_name' => '', 'save_path' => '', 'error' => 6]; // cURL 錯誤
        }
        curl_close($ch);
    } else {
        // readfile + output buffering 方式(簡單但無法精細控制逾時/標頭)
        ob_start();
        $result = @readfile($url);
        $img = ob_get_contents();
        ob_end_clean();
        if ($result === false) {
            return ['file_name' => '', 'save_path' => '', 'error' => 7]; // 讀取失敗
        }
    }

    // 寫入檔案
    $filepath = $save_dir . $filename;
    $fp = @fopen($filepath, 'wb'); // 使用二進位模式
    if (!$fp) {
        return ['file_name' => '', 'save_path' => '', 'error' => 8]; // 無法開啟檔案
    }
    fwrite($fp, $img);
    fclose($fp);

    return [
        'file_name' => $filename,
        'save_path' => $filepath,
        'error'     => 0
    ];
}
?>

呼叫範例

<?php
require_once 'getImage.func.php'; // 假設函式存放於此檔案

$url = 'https://example.com/images/photo.jpg';
$result = getImage($url, 'uploads/images/');

if ($result['error'] === 0) {
    echo "下載成功!檔案儲存於:{$result['save_path']}";
} else {
    $errors = [
        1 => 'URL 不得為空',
        3 => '不支援的圖片格式',
        5 => '無法建立儲存目錄',
        6 => 'cURL 下載失敗',
        7 => 'readfile 讀取失敗',
        8 => '無法寫入檔案',
    ];
    echo "下載失敗:{$errors[$result['error']] ?? '未知錯誤'} (代碼:{$result['error']})";
}
?>

進階優化建議

  1. 檔案雜湊去重:下載前先計算遠端檔案 SHA256,本地若已存在相同雜湊則略過下載。
  2. 非同步處理:大量圖片下載時,建議使用工作佇列(如 Redis + Worker)離線處理,避免阻塞 HTTP 請求。
  3. 安全性加強:
    • 驗證 Content-Type 標頭確為圖片類型。
    • 使用 getimagesizefromstring() 驗證檔案真偽,防止惡意腳本偽裝圖片上傳。
    • 儲存目錄設定 open_basedir 限制,禁止執行權限。
  4. 支援更多格式:擴充副檔名白名單至 .webp、.avif 等現代格式。

常見錯誤代碼對照表

代碼說明
0成功
1URL 為空
3不支援的副檔名(非 gif/jpg/png)
5目錄建立失敗(權限不足)
6cURL 執行錯誤(連線逾時、DNS 失敗等)
7readfile 讀取失敗(URL 無效、允許 url_fopen 關閉)
8檔案寫入失敗(磁碟空間不足、權限問題)

總結

透過封裝 getImage() 函式,即可輕鬆實現遠端圖片下載與本地儲存。實務部署時,請根據專案需求選擇 cURL 或原生函式,並務必加入檔案驗證與安全防護措施,確保系統穩定與安全。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved