Go 標(biāo)準(zhǔn)庫(kù)的神秘功能:如何輕松識(shí)別任何文件類(lèi)型
閱讀本文大概需要 2 分鐘。
文件類(lèi)型識(shí)別是在很多應(yīng)用場(chǎng)景中都需要用到的功能,比如在 Web 開(kāi)發(fā)中,我們需要根據(jù)上傳文件的類(lèi)型來(lái)進(jìn)行不同的處理,或者在文件管理系統(tǒng)中,我們需要根據(jù)文件類(lèi)型來(lái)顯示不同的圖標(biāo)和操作。文件類(lèi)型識(shí)別的常用方法有兩種:一種是根據(jù)文件的擴(kuò)展名來(lái)判斷,比如 .jpg 表示 JPEG 圖像,.mp3 表示 MP3 音頻等;另一種是根據(jù)文件內(nèi)容的特征來(lái)判斷,比如 JPEG 圖像的前幾個(gè)字節(jié)是 FF D8 FF,MP3 音頻的前幾個(gè)字節(jié)是 ID3 等。這兩種方法各有優(yōu)缺點(diǎn),擴(kuò)展名方法簡(jiǎn)單快速,但是容易被偽造或者缺失;內(nèi)容特征方法準(zhǔn)確可靠,但是需要讀取文件內(nèi)容并進(jìn)行分析。
Go 語(yǔ)言的標(biāo)準(zhǔn)庫(kù) net/http 包中提供了一個(gè)簡(jiǎn)單的判斷文件類(lèi)型的方法 DetectContentType() 。它讀取文件內(nèi)容的前 512 個(gè)字節(jié)內(nèi)容,返回一個(gè) MIME 類(lèi)型字符串,例如 image/jpeg。它使用了 mimesniff 算法2?,根據(jù)一組預(yù)定義的規(guī)則來(lái)匹配文件內(nèi)容的特征和對(duì)應(yīng)的 MIME 類(lèi)型。這個(gè)方法既不依賴于文件擴(kuò)展名,也不需要完整地讀取文件內(nèi)容,因此既快速又準(zhǔn)確。
下面我們來(lái)看一個(gè)使用 Go 語(yǔ)言識(shí)別 MP3 文件格式的示例:
package?main
import?(
?"fmt"
?"net/http"
?"os"
)
func?main()?{
?//?打開(kāi)一個(gè)?MP3?文件
?file,?err?:=?os.Open("example.mp3")
?if?err?!=?nil?{
??fmt.Println(err)
??return
?}
?defer?file.Close()
?//?讀取文件的前?512?個(gè)字節(jié)
?buffer?:=?make([]byte,?512)
?n,?err?:=?file.Read(buffer)
?if?err?!=?nil?{
??fmt.Println(err)
??return
?}
?//?調(diào)用?http.DetectContentType?方法判斷文件類(lèi)型
??//?實(shí)際上,如果字節(jié)數(shù)超過(guò)?512,該函數(shù)也只會(huì)使用前?512?個(gè)字節(jié)
?contentType?:=?http.DetectContentType(buffer[:n])
?fmt.Println(contentType)?//?輸出?audio/mpeg
}
這個(gè)示例中,我們首先打開(kāi)了一個(gè) MP3 文件,并讀取了它的前 512 個(gè)字節(jié)到一個(gè)緩沖區(qū)中。然后我們調(diào)用了 http.DetectContentType 方法,并傳入了緩沖區(qū)中的數(shù)據(jù)。這個(gè)方法會(huì)返回一個(gè)字符串表示文件的 MIME 類(lèi)型,對(duì)于 MP3 文件來(lái)說(shuō),就是 audio/mpeg。
此外,返回的 contentType 可以通過(guò)以下方式返回具體的擴(kuò)展名:
//?上面?mp3?文件返回的會(huì)是?.mp3,注意包含?.
ext?:=?mime.ExtensionsByType(contentType)
在本文中,我們介紹了文件類(lèi)型識(shí)別的應(yīng)用場(chǎng)景和常用方法,并且以 Go 語(yǔ)言為例,展示了如何使用 http.DetectContentType 方法來(lái)識(shí)別 MP3 文件格式。這個(gè)方法是 Go 標(biāo)準(zhǔn)庫(kù)提供的一個(gè)簡(jiǎn)單而有效的判斷文件類(lèi)型的方法,可以在很多場(chǎng)合中使用。我們希望這篇文章能夠?qū)δ阌兴鶐椭?/p>
如果你遇到了無(wú)法識(shí)別的文件或識(shí)別不準(zhǔn),怎么辦?請(qǐng)期待后續(xù)文章。
往期推薦
我是 polarisxu,北大碩士畢業(yè),曾在 360 等知名互聯(lián)網(wǎng)公司工作,10多年技術(shù)研發(fā)與架構(gòu)經(jīng)驗(yàn)!2012 年接觸 Go 語(yǔ)言并創(chuàng)建了 Go 語(yǔ)言中文網(wǎng)!著有《
Go語(yǔ)言編程之旅
》、開(kāi)源圖書(shū)《
Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)
》等。
堅(jiān)持輸出技術(shù)(包括 Go、Rust 等技術(shù))、職場(chǎng)心得和創(chuàng)業(yè)感悟!歡迎關(guān)注「polarisxu」一起成長(zhǎng)!也歡迎加我微信好友交流: gopherstudio
