利用html5識別文件類型


一般,在文件上傳時,咱們只會根據文件的擴展名來識別並限制所上傳的文件類型。 
好比只容許上傳 Excel,那麼咱們將會查看文件的擴展名是否是.xls/.xlsxhtml

但咱們知道,在windows系統中,咱們能夠任意更改文件的擴展名。 那麼若是某些用戶,將一個zip的壓縮文件,改成 .xls,在上傳時,單單經過擴展名來識別文件,那麼它必定是能夠經過的。
不少時候,用戶都會利用這個漏洞,上傳一些看似合法的文件,就如上述場景,將盜版的視頻文件改成.pdf,跳過審查(某些論壇就是這麼幹的)。前端

需求場景windows

小A: 「呀,網盤不能上傳視頻了,咋辦?」後端

大B:」什麼狀況?」瀏覽器

小A:」我一上傳mp4的文件,它就提示文件名不合法…」服務器

大B:」把擴展名改爲pdf試下,下載看的時候,再改過來。」app

async

小A:」真的能夠了誒! 膜拜大神!」測試

那麼咱們是否能夠經過某些方法,來識別出這類「非法」文件呢?spa

若是文件擴展名改了,本來的文件內容會變嗎?

固然不會…

咱們能夠作個實驗,好比本來就是一個視頻文件,咱們改掉擴展名後,再用播放器打開。 測試會發現,播放器同樣能夠播放該視頻。

那麼就是說,咱們能夠經過讀取文件內容,來具體識別出文件類型。

原理在此簡單介紹下,其實在每一個文件生成時,都會有個File Signature (亦稱magic number)。 通常都會在文件頭處(即前4 ~ 8位字節)。所以,咱們能夠將此段讀取出來,與File Signature的庫對應,便可找到實際的文件類型。

網上不少的解決方法,都是經過將文件上傳到服務器以後,經過後端語言讀取識別。

但這樣就會產生必定的延遲,若是遇到較大的文件,讓用戶等待的時間則過長,體驗並很差。

在此,着重介紹一下,若是利用HTML5的新特性FileReader,直接在瀏覽器中讀取文件內容並識別類型。

利用HTML5直接識別文件類型

不廢話,上源碼

實際應用

好了,上述核心功能已介紹完成。但使用時,會發現,不過的文件類型,它的Signature的要求是不一樣的。 
有些是前8位字節,有些則是前4位字節。而有些則不是從文件頭開始的,須要從512字節開始讀取。
更變態的是,同一擴展名會有多個Signature。

所以,在實際運用時,咱們並不能只截取文件的前幾位字節來識別。那如何能夠準備識別文件類型呢?
目前思路以下,單獨創建一個庫,先根據所上傳文件的擴展名,找到它所須要截取的文件部分,讀取後對應其Signature,若是不匹配,則說明該文件類型與擴展名是不符合的。

目前,我創建的庫以下,分別包含每一個文件擴展名對應的Signature,文件截取位置(offset),及截取大小(sizet)。



        onLoad(isMatch, signature); // async load callbacks       
    };       
    reader.readAsArrayBuffer(slice); // Read the slice of the file  
}

總結

目前經過純前端讀取文件內容來識別文件類型,能夠算是最快最簡潔的方法。

但一樣也存在一些缺陷:

1. 部分文件類型的Signature徹底同樣,並不是能徹底區分開

如微軟的Office系列文件,.xlsx,.docx,.pptx,其Signature是徹底同樣的。

拿了幾個文件來測試,結果以下:

相關文章
相關標籤/搜索