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

PHP 實現遠程圖片本地化(采集入庫)完整代碼

     編輯:PHP 綜合知識

需求場景

內容采集、編輯器粘貼外鏈圖片時,需將遠程圖片下載到本地服務器,並替換內容中的 src 地址,防止圖片丟失、盜鏈或跨域問題。

核心思路

  1. 使用 preg_match_all 正則提取 HTML 中所有 src="https://..." 的圖片 URL;
  2. 通過 cURL 獲取圖片二進制數據及 Content-Type;
  3. 按日期創建存儲目錄,生成唯一文件名保存;
  4. 將內容中的遠程 URL 替換為本地相對路徑。

完整實現代碼

 $url,
        CURLOPT_SSL_VERIFYPEER => 0,
        CURLOPT_SSL_VERIFYHOST => 1,
        CURLOPT_USERAGENT => $_SERVER['HTTP_USER_AGENT'],
        CURLOPT_FOLLOWLOCATION => 1,
        CURLOPT_REFERER => $ref ?: '',
        CURLOPT_AUTOREFERER => !$ref,
        CURLOPT_COOKIEJAR => $cookie_file,
        CURLOPT_COOKIEFILE => $cookie_file,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_HEADER => $head ? 1 : 0,
        CURLOPT_RETURNTRANSFER => 1,
    ]);
    $data = curl_exec($curl);
    $errno = curl_errno($curl);
    $info = $head ? curl_getinfo($curl) : [];
    curl_close($curl);
    if ($errno) error_log("cURL Error: " . curl_error($curl));
    return ['data' => $data, 'head' => $info];
}

/** 遞歸創建目錄 */
function MkdirAll($truepath) {
    global $cfg_dir_purview;
    if (!file_exists($truepath)) {
        MkdirAll(dirname($truepath));
        mkdir($truepath, $cfg_dir_purview);
        chmod($truepath, $cfg_dir_purview);
    }
    return true;
}

/** 核心:遠程圖片本地化 */
function GetCurContent($body) {
    global $cfg_basedir, $cfg_dir_purview;
    $basehost = "https://" . $_SERVER["HTTP_HOST"];
    $cfg_uploaddir = '/uploads';
    $imgUrl = $cfg_uploaddir . '/' . date("ymd");
    $imgPath = $cfg_basedir . $imgUrl;

    if (!is_dir($imgPath)) MkdirAll($imgPath);

    // 提取所有 https:// 開頭的 gif/jpg/png 圖片
    preg_match_all('/src=["\'\s]*((https?:\/\/[^>"\']+\.(gif|jpg|png)))/isU', $body, $matches);
    $img_array = array_unique($matches[1]);

    foreach ($img_array as $key => $value) {
        // 跳過本站圖片
        if (strpos($value, $basehost) !== false) continue;
        if (!preg_match('#^https?://#i', $value)) continue;

        $http = pget($value, $value, true);
        $ctype = $http['head']['content_type'] ?? '';
        // 根據 Content-Type 確定副檔名
        if (preg_match('#image/gif#i', $ctype)) $ext = '.gif';
        elseif (preg_match('#image/png#i', $ctype)) $ext = '.png';
        else $ext = '.jpg';

        $randName = rand(1000,9999) . rand(1000,9999) . '-' . $key . $ext;
        $rndFileName = $imgPath . '/' . $randName;
        $fileurl = $imgUrl . '/' . $randName;

        $fp = fopen($rndFileName, 'wb');
        fwrite($fp, $http['data']);
        fclose($fp);

        if (file_exists($rndFileName)) {
            $body = str_replace($value, $fileurl, $body);
        }
    }
    return $body;
}

// 使用示例
$content = '

'; echo GetCurContent($content);

關鍵點解析

  • 正則優化:使用非貪婪匹配 .*? 避免跨標簽匹配;
  • cURL 設置:啟用 CURLOPT_FOLLOWLOCATION 處理 302 跳轉;CURLOPT_SSL_VERIFYPEER=0 兼容 HTTPS 自簽名證書;
  • 文件命名:時間戳 + 隨機數 + 序號,極大降低衝突概率;
  • 錯誤處理:生產環境建議加入日誌記錄、重試機制、圖片尺寸/大小校驗。

擴展建議

  1. 支持 data:image/...;base64,... 格式內聯圖片解析;
  2. 接入對象存儲(OSS/COS/S3)替代本地磁盤;
  3. 異步隊列處理大批量采集任務,避免 PHP 超時。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved