Go 標準庫中隱藏了一個文件類型識別的寶貝
文件類型識別是在很多應用場景中都需要用到的功能,比如在 Web 開發中,我們需要根據上傳文件的類型來進行不同的處理,或者在文件管理系統中,我們需要根據文件類型來顯示不同的圖標和操作。文件類型識別的常用方法有兩種:一種是根據文件的擴展名來判斷,比如 .jpg 表示 JPEG 圖像,.mp3 表示 MP3 音頻等;另一種是根據文件內容的特徵來判斷,比如 JPEG 圖像的前幾個字節是 FF D8 FF,MP3 音頻的前幾個字節是 ID3 等。這兩種方法各有優缺點,擴展名方法簡單快速,但是容易被僞造或者缺失;內容特徵方法準確可靠,但是需要讀取文件內容並進行分析。
Go 語言的標準庫 net/http 包中提供了一個簡單的判斷文件類型的方法 DetectContentType() 。它讀取文件內容的前 512 個字節內容,返回一個 MIME 類型字符串,例如 image/jpeg。它使用了 mimesniff 算法 ²⁴,根據一組預定義的規則來匹配文件內容的特徵和對應的 MIME 類型。這個方法既不依賴於文件擴展名,也不需要完整地讀取文件內容,因此既快速又準確。
下面我們來看一個使用 Go 語言識別 MP3 文件格式的示例:
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
// 打開一個 MP3 文件
file, err := os.Open("example.mp3")
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
// 讀取文件的前 512 個字節
buffer := make([]byte, 512)
n, err := file.Read(buffer)
if err != nil {
fmt.Println(err)
return
}
// 調用 http.DetectContentType 方法判斷文件類型
// 實際上,如果字節數超過 512,該函數也只會使用前 512 個字節
contentType := http.DetectContentType(buffer[:n])
fmt.Println(contentType) // 輸出 audio/mpeg
}
這個示例中,我們首先打開了一個 MP3 文件,並讀取了它的前 512 個字節到一個緩衝區中。然後我們調用了 http.DetectContentType 方法,並傳入了緩衝區中的數據。這個方法會返回一個字符串表示文件的 MIME 類型,對於 MP3 文件來說,就是 audio/mpeg。
此外,返回的 contentType 可以通過以下方式返回具體的擴展名:
// 上面 mp3 文件返回的會是 .mp3,注意包含 .
ext := mime.ExtensionsByType(contentType)
在本文中,我們介紹了文件類型識別的應用場景和常用方法,並且以 Go 語言爲例,展示瞭如何使用 http.DetectContentType 方法來識別 MP3 文件格式。這個方法是 Go 標準庫提供的一個簡單而有效的判斷文件類型的方法,可以在很多場合中使用。我們希望這篇文章能夠對你有所幫助。
如果你遇到了無法識別的文件或識別不準,怎麼辦?請期待後續文章。
我是 polarisxu,北大碩士畢業,曾在 360 等知名互聯網公司工作,10 多年技術研發與架構經驗!2012 年接觸 Go 語言並創建了 Go 語言中文網!著有《Go 語言編程之旅》、開源圖書《Go 語言標準庫》等。
堅持輸出技術(包括 Go、Rust 等技術)、職場心得和創業感悟!歡迎關注「polarisxu」一起成長!也歡迎加我微信好友交流:gopherstudio
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/spUKBQB_Ig6ANabbP4FG8g