在處理使用者上傳圖片時,常需快速取得寬高、格式、檔案大小等中繼資料。本文提供一個封裝 getimagesize() 的實用函式 getImageInfo(),回傳結構化陣列,並修正原版程式碼的語法錯誤與邏輯缺失。
<?php
/**
* 取得圖片完整資訊
* @param string $imgPath 圖片絕對路徑或相對路徑
* @return array|false 成功回傳關聯陣列,失敗回傳 false
* ['width' => int, 'height' => int, 'type' => string, 'mime' => string, 'size' => string, 'size_bytes' => int]
*/
function getImageInfo(string $imgPath) {
// 1. 基本檢查
if (!file_exists($imgPath) || !is_readable($imgPath)) {
trigger_error("圖片檔案不存在或不可讀取: {$imgPath}", E_USER_WARNING);
return false;
}
// 2. 核心解析:getimagesize() 回傳陣列 [0=寬, 1=高, 2=型別常數, 3=HTML屬性字串, bits, channels, mime]
$info = @getimagesize($imgPath);
if ($info === false) {
trigger_error("無法解析圖片資訊 (非支援格式或損壞): {$imgPath}", E_USER_WARNING);
return false;
}
// 3. 型別常數對照表 (IMAGETYPE_XXX 常數)
$typeMap = [
IMAGETYPE_GIF => 'GIF',
IMAGETYPE_JPEG => 'JPEG',
IMAGETYPE_PNG => 'PNG',
IMAGETYPE_WEBP => 'WEBP',
IMAGETYPE_BMP => 'BMP',
IMAGETYPE_TIFF_II => 'TIFF',
IMAGETYPE_TIFF_MM => 'TIFF',
IMAGETYPE_JPEG2000 => 'JPEG2000',
IMAGETYPE_ICO => 'ICO',
];
$typeConst = $info[2];
$typeName = $typeMap[$typeConst] ?? 'UNKNOWN';
// 4. 檔案大小格式化
$bytes = filesize($imgPath);
$sizeHuman = match (true) {
$bytes >= 1024*1024*1024 => sprintf('%.2f GB', $bytes / (1024*1024*1024)),
$bytes >= 1024*1024 => sprintf('%.2f MB', $bytes / (1024*1024)),
$bytes >= 1024 => sprintf('%.2f KB', $bytes / 1024),
default => "{$bytes} Bytes",
};
// 5. 回傳結構化資料
return [
'width' => $info[0],
'height' => $info[1],
'type' => $typeName,
'mime' => $info['mime'] ?? '', // 如 'image/jpeg'
'size' => $sizeHuman, // 人類可讀格式
'size_bytes' => $bytes, // 原始位元組數
'ratio' => $info[0] / $info[1], // 長寬比
'orientation'=> $info[0] > $info[1] ? 'landscape' : ($info[0] < $info[1] ? 'portrait' : 'square'),
];
}
?>
<?php
$img = 'uploads/photo.jpg';
$info = getImageInfo($img);
if ($info) {
echo "寬度: {$info['width']}px
";
echo "高度: {$info['height']}px
";
echo "格式: {$info['type']} ({$info['mime']})
";
echo "大小: {$info['size']} ({$info['size_bytes']} bytes)
";
echo "長寬比: " . number_format($info['ratio'], 2) . "
";
echo "方向: {$info['orientation']}
";
// 實務應用:驗證上傳圖片規格
if ($info['width'] > 1920 || $info['height'] > 1080) {
echo "⚠ 圖片尺寸超過 1920x1080,建議壓縮";
}
if ($info['size_bytes'] > 2 * 1024 * 1024) {
echo "⚠ 檔案大小超過 2MB";
}
if (!in_array($info['type'], ['JPEG', 'PNG', 'WEBP'])) {
echo "❌ 不支援的格式,僅允許 JPEG/PNG/WEBP";
}
} else {
echo "圖片資訊讀取失敗";
}
?>
手機拍攝的照片常含 EXIF 方向標籤,顯示時需自動旋轉。可擴充函式讀取 EXIF:
function getImageInfoEx(string $imgPath): array|false {
$basic = getImageInfo($imgPath);
if (!$basic) return false;
$exif = @exif_read_data($imgPath, 'IFD0');
if ($exif && isset($exif['Orientation'])) {
$orientation = (int)$exif['Orientation'];
// 根據 Orientation 值 (1-8) 判斷實際寬高是否需互換
if (in_array($orientation, [5, 6, 7, 8])) {
// 旋轉 90/270 度會導致寬高互換
$basic['width'] = $basic['height'];
$basic['height'] = $basic['width']; // 注意此處邏輯需暫存
$basic['exif_rotated'] = true;
}
$basic['exif_orientation'] = $orientation;
}
return $basic;
}
getimagesize('https://example.com/img.jpg') 可直接讀取遠端圖片,但需開啟 allow_url_fopen=On,且較慢、不穩定。建議先下載至暫存檔再分析。getimagesize() 不支援 SVG(XML 文字格式)。需自行解析 XML 取得 width/height 屬性或 viewBox。memory_limit。可暫時調高或使用 ImageMagick identify 指令列工具。$info[2] (IMAGETYPE_XXX) 判斷格式,不可信任副檔名,防止偽裝檔案上傳。getImageInfo() 將 getimagesize() 的原始回傳值轉換為語意清晰、單位友善的關聯陣列,並補充長寬比、方向判斷等實務常用衍生資訊。搭配 EXIF 讀取與格式白名單驗證,可構建健全的圖片上傳前置檢查機制。