瀏覽代碼

API images: measure size from the local file, once per request (#5756)

bx_api_get_image() falls back to measuring an image when its storage
row has no stored dimensions (e.g. the Ads photos/covers storages have
no dimensions column). It did that with BxDolImageResize on the public
URL: the server downloaded and decoded its own image over HTTPS on
every call, 3-4 times per image per request.

Read the header of the local file with getimagesize() when the storage
has one (getFileLocalPath), fall back to the URL otherwise, and keep the
result per URL for the rest of the request.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Andrey Yasko 2 周之前
父節點
當前提交
d5a43965e8
共有 1 個文件被更改,包括 20 次插入 和 3 次删除
  1. 20 3
      inc/utils.inc.php

+ 20 - 3
inc/utils.inc.php

@@ -2734,6 +2734,7 @@ function bx_api_get_image($mixedStorage, $iId)
         }
     }
 
+    $sLocalPath = '';
     if(!$sUrl && ($oS = BxDolStorage::getObjectInstance($sStorage))) {
         $sUrl = $oS->getFileUrlById($iId);
 
@@ -2742,12 +2743,28 @@ function bx_api_get_image($mixedStorage, $iId)
             $iWidth = (int)$aTmp[0];
             $iHeight = (int)$aTmp[1];
         }
+        else
+            $sLocalPath = $oS->getFileLocalPath($iId);
     }
 
     if(!$iWidth && !$iHeight && $sUrl) {
-        $aSize = BxDolImageResize::getInstance()->getImageSize($sUrl);
-        $iWidth = (int)$aSize['w'];
-        $iHeight = (int)$aSize['h'];
+        // Without stored dimensions the size used to be measured by downloading the
+        // image from its own public URL and decoding it, on every call (several times
+        // per feed item). Read the header of the local file when there is one, and
+        // measure each URL only once per request.
+        static $aSizes = [];
+        if(!isset($aSizes[$sUrl])) {
+            $aSize = false;
+            if($sLocalPath && ($aInfo = @getimagesize($sLocalPath)))
+                $aSize = ['w' => $aInfo[0], 'h' => $aInfo[1]];
+            if(!$aSize)
+                $aSize = BxDolImageResize::getInstance()->getImageSize($sUrl);
+            $aSizes[$sUrl] = $aSize;
+        }
+
+        $aSize = $aSizes[$sUrl];
+        $iWidth = (int)($aSize['w'] ?? 0);
+        $iHeight = (int)($aSize['h'] ?? 0);
     }
 
     if(!$iWidth && !$iHeight) {