python-magic:最實用的「以內容判斷文件類型」方法
當伺服器具備圖片上傳功能時,往往會遇到以下需求。
- 「
.png這個檔案真的 PNG 嗎?」 - 「先判斷這個檔案是圖片還是文件,再決定處理方式。」
- 「在使用 Pillow/OpenCV 等外部解析器之前,先確認檔案類型。」
此時最堅實的起點不是「副檔名」,而是「檔案內容」。
而「以內容判斷」最簡單的工具就是 python-magic。
python-magic 是什麼?
python-magic 是一個將 C 語言函式庫 libmagic 包裝成 Python 可用的工具。libmagic 透過檢查檔案的「頭部(前幾個位元組)」等特徵來辨識檔案類型,這個功能在 Unix 的 file 指令中也能看到。
簡而言之:
file(Linux 指令)=「在終端機使用的介面」libmagic= 「核心引擎(判斷邏輯)」python-magic= 「在 Python 中呼叫 libmagic 的薄包裝」
本文將以 python-magic 為核心,結構化說明「這個引擎究竟如何判斷檔案類型」。
libmagic 的工作原理

libmagic 的核心概念很簡單:
「讀取包含檔案類型判斷規則的資料庫,依照規則檢查檔案位元組,並給出最合理的結論。」
這個資料庫即為 magic database(魔法模式資料庫),file/libmagic 共同使用。通常以編譯後的二進位檔(magic.mgc)安裝在系統中。
1) 「魔法檔」是規則集合
這些規則主要包含:
- 要檢查的位置(offset:檔案的哪個位元組)
- 讀取方式(type:位元組/字串/整數等)
- 比較目標(expected value/pattern)
- 判斷結論(message/MIME 等)
file 的手冊也說明它在檢查「magic patterns」。規則逐行測試(offset/type/value/message),若符合則進一步進入更具體的子測試,形成「層級結構」。
想了解 Linux file 指令的詳細資訊,請點擊以下連結。
2) 規則資料庫有「文字原始」與「編譯結果」
魔法資料庫原本是人類可讀的文字片段,為了效能,通常也提供編譯後的二進位資料庫(.mgc)。
3) 目的:以內容判斷檔案類型
file 之所以被視為「以內容判斷檔案類型」的工具,已是長久以來的哲學。python-magic 就是把這個哲學「以一行 Python 代碼」帶進來的工具。
如何使用 python-magic
常見的使用模式有兩種。
1) 取得 MIME 類型(最實用)
適用於上傳處理、路由、日誌/指標。
import magic
mime = magic.from_file("upload.bin", mime=True)
print(mime) # 例如: image/png
python-magic 以 libmagic 為基礎提供檔案類型辨識,功能與 file 指令相同,官方說明亦如此。
2) 直接以位元組判斷(上傳流時更方便)
在將檔案寫入磁碟前,只需檢查上傳的前幾個位元組即可快速判斷。
import magic
with open("upload.bin", "rb") as f:
head = f.read(4096)
mime = magic.from_buffer(head, mime=True)
print(mime)
(基於緩衝區的判斷特別適合作為「檔案寫入前的第一道過濾器」)
從開發者角度看其實用性
1) 上傳驗證的第一道防線
- 不僅依賴副檔名
- 先確認「這個檔案能否被當作圖片處理」
2) 處理流程的分流點
- 若是圖片 → 進入縮放/縮圖流程
- 若是 PDF/ZIP → 交給其他工作者
- 若是未知類型 → 隔離/拒絕/進一步驗證
3) 在呼叫「重量級解碼器」前降低成本
Pillow 等解碼器雖強大,但呼叫本身會消耗記憶體/CPU,甚至擴大攻擊面。python-magic 可先判斷「是否值得進一步處理」。
重要實務提醒:libmagic 只是一個推測/辨識工具。若安全性是首要目標,仍需額外驗證(白名單、大小限制、沙盒解碼等)。
小結:python-magic 是「以程式碼輕鬆取得檔案類型」的最佳選擇
- 不是用來處理圖片,而是告訴你「這個檔案應該怎麼對待」
- 引擎:
file/libmagic - 判斷方式:規則資料庫 + 位元組檢查
- 在實務中,特別適合上傳驗證、路由決策、成本節省
掌握後,即使在缺乏其他庫的環境,也能構建「判斷 → 分流 → 安全防護」的流程。
下一篇預告
- 解析 Pillow(PIL)的
open()、load()、verify()各自保證什麼,何時使用,如何運作。
相關文章
目前沒有評論。