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

PHP 正則匹配文章遠程圖片並下載儲存至本地:完整實作與效能優化

     編輯:PHP 綜合知識

需求場景

編輯器貼上外部圖片連結時,為避免防盜鏈、提升載入速度、確保資料可控,需自動下載遠程圖片至本地伺服器,並替換文章內容中的圖片連結。

核心實作步驟

1. 正則匹配所有遠程圖片 URL

$pattern = '/(src|SRC)=["\'\s]*((https?):\/\/[^\s"\'<>]+?\.(gif|jpg|jpeg|bmp|png))/isU';
preg_match_all($pattern, $content, $matches);
$imageUrls = array_unique($matches[2]); // 去重

2. 建立儲存目錄結構

$basePath = $_SERVER['DOCUMENT_ROOT'] . '/uploads/images/';
$dateDir = $basePath . date('Ymd/');
$dateUrl = '/uploads/images/' . date('Ymd/');
if (!is_dir($dateDir)) {
    mkdir($dateDir, 0755, true);
}

3. 下載並儲存圖片

set_time_limit(0); // 移除執行時間限制
foreach ($imageUrls as $url) {
    $url = trim($url);
    $imageData = @file_get_contents($url);
    if (!$imageData) continue;
    
    // 產生唯一檔名:時間戳 + 隨機數 + 副檔名
    $ext = strtolower(pathinfo($url, PATHINFO_EXTENSION));
    $ext = in_array($ext, ['jpg','jpeg','png','gif','bmp']) ? $ext : 'jpg';
    $fileName = date('YmdHis') . '_' . mt_rand(10000, 99999) . '.' . $ext;
    $filePath = $dateDir . $fileName;
    $fileUrl  = $dateUrl . $fileName;
    
    file_put_contents($filePath, $imageData);
    
    // 替換文章內容中的原始 URL
    $content = str_replace($url, $fileUrl, $content);
}

關鍵優化與注意事項

效能優化

  • 使用 curl_multi 並發下載大量圖片
  • 檢查檔案是否已存在(MD5 比對)避免重複下載
  • 設定合理的 timeout 避免卡死
  • 非同步佇列處理(如 RabbitMQ、Redis Queue)

安全防護

  • 驗證 Content-Type 確認為圖片格式
  • 限制單張圖片大小(如 5MB)
  • 使用 getimagesize() 二次驗證圖片有效性
  • 檔名隨機化,防止路徑遍歷攻擊

錯誤處理與日誌

$success = 0; $failed = [];
foreach ($imageUrls as $url) {
    try {
        // 下載邏輯...
        $success++;
    } catch (Exception $e) {
        $failed[] = ['url' => $url, 'error' => $e->getMessage()];
    }
}
// 記錄失敗清單供人工處理
if ($failed) error_log('Image download failed: ' . json_encode($failed));

現代化替代方案

考慮使用成熟函式庫:

  • Guzzle:強大的 HTTP 客戶端,支援並發、重試、中介軟體
  • Intervention Image:圖片處理、壓縮、水印、格式轉換
  • Flysystem:統一儲存抽象層,支援本地、S3、FTP、雲端儲存

建立健全的遠程圖片本地化機制,不僅能提升網站效能與安全性,更能掌握內容資料的完整控制權。

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