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

PHP 取得檔案 MIME 類型三種方法:mime_content_type、Fileinfo、image_type_to_mime_type

     編輯:PHP 綜合知識

準確判斷檔案 MIME 類型對安全上傳、內容協商、檔案處理至關重要。本文比較三種主流方法的優缺點、安裝需求、適用場景與程式碼範例。

方法比較總覽

方法PHP 版本擴展需求支援檔案類型準確度推薦度
mime_content_type()< 5.3無 (內建)所有中❌ 已棄用
Fileinfo (finfo)5.3+fileinfo所有高✅ 官方推薦
image_type_to_mime_type()4.3+exif + mbstring僅圖片極高✅ 圖片專用

方法 1:mime_content_type() (已棄用)

<?php
// PHP 5.3+ 會產生 E_DEPRECATED 警告
$mime = mime_content_type('image.jpg');
echo $mime; // image/jpeg

// 依賴 magic.mime 檔案,準確度受系統資料庫影響
?>

方法 2:Fileinfo (finfo) - 官方推薦標準

安裝啟用

# Ubuntu/Debian
apt-get install php-fileinfo
# 或編譯時加入 --enable-fileinfo

# CentOS/RHEL
yum install php-pecl-fileinfo
# PHP 7.4+ 通常內建啟用

# Windows: php.ini 取消註解
extension=fileinfo

使用範例

<?php
// 物件導向風格 (推薦)
$finfo = new finfo(FILEINFO_MIME_TYPE); // 僅回傳 MIME 類型
$mime = $finfo->file('document.pdf');
echo $mime; // application/pdf

// 程序風格
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, 'video.mp4');
finfo_close($finfo);

// 取得更多資訊
$finfo = new finfo(FILEINFO_MIME); // MIME + 編碼
$result = $finfo->file('test.txt'); // text/plain; charset=us-ascii
?>

方法 3:image_type_to_mime_type() - 圖片專用高精度

安裝需求

# 需 exif 擴展 (通常需 mbstring)
# php.ini
extension=mbstring
extension=exif

# 注意:exif 必須在 mbstring 之後載入

使用範例

<?php
// 1. 先用 exif_imagetype 偵測圖片類型常數
$imageType = exif_imagetype('photo.jpg'); // 回傳 IMAGETYPE_JPEG (2)

// 2. 轉換為 MIME 字串
$mime = image_type_to_mime_type($imageType);
echo $mime; // image/jpeg

// 常見圖片類型常數對照
$types = [
    IMAGETYPE_GIF   => 'image/gif',
    IMAGETYPE_JPEG  => 'image/jpeg',
    IMAGETYPE_PNG   => 'image/png',
    IMAGETYPE_WEBP  => 'image/webp',
    IMAGETYPE_BMP   => 'image/bmp',
    IMAGETYPE_ICO   => 'image/vnd.microsoft.icon',
];
?>

安全上傳最佳實踐:雙重驗證

<?php
function validateUploadedFile($tmpPath, array $allowedMimes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']) {
    // 1. Fileinfo 驗證 (主要防禦)
    $finfo = new finfo(FILEINFO_MIME_TYPE);
    $mime = $finfo->file($tmpPath);
    
    if (!in_array($mime, $allowedMimes, true)) {
        throw new Exception("不允許的檔案類型: $mime");
    }
    
    // 2. 圖片專用二次驗證 (防禦深度)
    if (str_starts_with($mime, 'image/')) {
        $imageType = @exif_imagetype($tmpPath);
        if ($imageType === false) {
            throw new Exception("無效的圖片檔案");
        }
        $mime2 = image_type_to_mime_type($imageType);
        if ($mime !== $mime2) {
            throw new Exception("MIME 類型不一致,疑似偽裝檔案");
        }
    }
    
    // 3. 可選:getimagesize() 驗證尺寸
    $size = @getimagesize($tmpPath);
    if ($size === false) {
        throw new Exception("無法讀取圖片尺寸");
    }
    
    return [
        'mime' => $mime,
        'width' => $size[0],
        'height' => $size[1],
        'type' => $size[2] // IMAGETYPE_* 常數
    ];
}
?>

避坑指南:副檔名不可信

❌ 錯誤做法:根據副檔名判斷類型
$ext = pathinfo($file, PATHINFO_EXTENSION);
攻擊者可上傳 shell.php.jpg 或修改副檔名繞過檢查。
✅ 正確做法:內容檢測 (Fileinfo/exif) + 副檔名白名單 雙重驗證
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved