Exif 擴展讓 PHP 能讀取圖片元數據(拍攝參數、GPS、設備信息等),是圖片處理、相簿系統、內容審核的基礎組件。本文詳解 php.ini 配置、擴展加載順序依賴、編碼設置、驗證測試與常見問題。
Exif 依賴 mbstring,且 mbstring 必須先於 Exif 加載。這是因為 Exif 內部處理字符串編碼轉換時調用 mbstring 函數。
加載順序:mbstring → exif
↑
必須先加載
# CLI
php --ini
# FPM/Apache 模塊
php -i | grep "Loaded Configuration File"
; 修改前
;extension=mbstring
;extension=exif
; 修改後 — 注意順序!
extension=mbstring
extension=exif
[exif]
; Exif 標籤編碼設置
exif.encode_unicode = ISO-8859-15
exif.decode_unicode_motorola = UCS-2BE
exif.decode_unicode_intel = UCS-2LE
exif.encode_jis =
exif.decode_jis_motorola = JIS
exif.decode_jis_intel = JIS
; === Extensions ===
extension=mbstring ; 必須在 exif 之前
extension=exif ; Exif 依賴 mbstring
; === Exif Settings ===
[exif]
exif.encode_unicode = ISO-8859-15
exif.decode_unicode_motorola = UCS-2BE
exif.decode_unicode_intel = UCS-2LE
exif.encode_jis =
exif.decode_jis_motorola = JIS
exif.decode_jis_intel = JIS
apt-get install php8.2-exif php8.2-mbstring |
| CentOS/RHEL/Rocky | yum install php-exif php-mbstring 或 dnf install php-exif php-mbstring |
| Alpine | apk add php82-exif php82-mbstring |
| Windows | PHP 內置,僅需 php.ini 啟用 |
| macOS (Homebrew) | brew install php@8.2 (默認包含) |
| Docker (官方鏡像) | docker-php-ext-install mbstring exif |
<?php
// 1. 檢查擴展是否加載
var_dump(extension_loaded('exif')); // bool(true)
var_dump(extension_loaded('mbstring')); // bool(true)
// 2. 檢查函數可用
var_dump(function_exists('exif_read_data')); // bool(true)
var_dump(function_exists('exif_thumbnail')); // bool(true)
// 3. 實際讀取測試
$testImage = __DIR__ . '/test.jpg'; // 需包含 Exif 的測試圖
if (file_exists($testImage)) {
$exif = exif_read_data($testImage, 'IFD0', true, false);
echo "Exif 數據:\n";
print_r($exif);
// 縮略圖提取
$thumb = exif_thumbnail($testImage);
if ($thumb !== false) {
file_put_contents('thumb.jpg', $thumb);
echo "縮略圖已提取: thumb.jpg\n";
}
} else {
echo "請準備一張包含 Exif 信息的測試圖片\n";
}
exif_read_data() | 讀取所有 Exif 標籤 | 關聯數組 / false |
| exif_thumbnail() | 提取嵌入縮略圖 | 二進制數據 / false |
| exif_imagetype() | 判斷圖片類型 (比 getimagesize 快) | 常量 IMAGETYPE_* |
| exif_get_tagname() | 獲取標籤名稱 | 字符串 |
exif_read_data() 返回 false | 圖片無 Exif、格式不支持、文件損壞 | 檢查文件、嘗試其他圖片 |
| 中文標籤亂碼 | 編碼設置缺失/錯誤 | 確保 mbstring 先加載,設置 exif.encode_unicode |
| Call to undefined function exif_read_data() | 擴展未啟用 | 檢查 php.ini、重啟 PHP-FPM/Apache |
| Windows 下 DLL 加載失敗 | 缺少 php_mbstring.dll | 確保 extension=mbstring 在 exif 前並啟用 |
| 性能慢 | 大文件讀取全部 Exif | 使用 exif_read_data($file, null, true, false) 只讀取 IFD0 |
Exif 標籤可能包含多種編碼:
PHP 內部使用 UTF-8,Exif 擴展需將讀取的 UCS-2/JIS 轉為 UTF-8,此過程調用 mb_convert_encoding(),故依賴 mbstring。
配置項 decode_unicode_motorola / decode_unicode_intel 分別指定兩種字節序下的 Unicode 解碼方式。
FROM php:8.2-fpm
RUN apt-get update && apt-get install -y \
libjpeg-dev libpng-dev libwebp-dev \
&& docker-php-ext-configure gd --with-jpeg --with-webp \
&& docker-php-ext-install -j$(nproc) \
mbstring \
exif \
gd \
pdo_mysql
<?php
// bootstrap/app.php 或中間件
if (!extension_loaded('exif') || !extension_loaded('mbstring')) {
throw new RuntimeException('Exif/Mbstring 擴展未加載,請檢查 php.ini 配置');
}
// 確保加載順序正確 (僅 CLI 可檢查,FPM 已固化)
$extensions = get_loaded_extensions();
$mbPos = array_search('mbstring', $extensions);
$exifPos = array_search('exif', $extensions);
if ($mbPos === false || $exifPos === false || $mbPos > $exifPos) {
error_log('警告: mbstring 應在 exif 之前加載');
}
<?php
// 只讀取 IFD0 (基本信息) 和 EXIF (拍攝參數),跳過 GPS、Interop 等
$exif = exif_read_data($imagePath, ['IFD0', 'EXIF'], true, false);
// 常用標籤映射
$tags = [
'Make' => $exif['IFD0']['Make'] ?? '', // 相機品牌
'Model' => $exif['IFD0']['Model'] ?? '', // 相機型號
'DateTime' => $exif['IFD0']['DateTime'] ?? '', // 拍攝時間
'ExposureTime' => $exif['EXIF']['ExposureTime'] ?? '', // 曝光時間
'FNumber' => $exif['EXIF']['FNumber'] ?? '', // 光圈
'ISOSpeedRatings' => $exif['EXIF']['ISOSpeedRatings'] ?? '', // ISO
'FocalLength' => $exif['EXIF']['FocalLength'] ?? '', // 焦距
];
extension=mbstring 必須在 extension=exif 之前[exif] 區塊設置 encode_unicode 等參數,防中文亂碼extension_loaded → function_exists → exif_read_data 實測sections 參數只讀取需要的標籤組配置正確後,exif_read_data() 即可穩定提取圖片的拍攝參數、設備信息、GPS 坐標等豐富元數據,為圖片管理、內容審核、智能分類提供強大數據支持。