利用html5識別文件類型

jklikhjk 8年前發布 | 12K 次閱讀 HTML5 前端技術

來自: http://my.oschina.net/u/2486271/blog/630778


 

通常,在文件上傳時,我們只會根據文件的擴展名來識別并限制所上傳的文件類型。 
比如只允許上傳 Excel,那么我們將會查看文件的擴展名是不是.xls/.xlsx

但我們知道,在windows系統中,我們可以任意更改文件的擴展名。 那么如果某些用戶,將一個zip的壓縮文件,改為 .xls,在上傳時,單單通過擴展名來識別文件,那么它一定是可以通過的。
很多時候,用戶都會利用這個漏洞,上傳一些看似合法的文件,就如上述場景,將盜版的視頻文件改為.pdf,跳過審查(某些論壇就是這么干的)。

需求場景

小A: “呀,網盤不能上傳視頻了,咋辦?”

大B:”什么情況?”

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

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

小A:”真的可以了誒! 膜拜大神!”

那么我們是否可以通過某些方法,來識別出這類“非法”文件呢?

如果文件擴展名改了,原本的文件內容會變嗎?

當然不會…

我們可以做個實驗,比如原本就是一個視頻文件,我們改掉擴展名后,再用播放器打開。 測試會發現,播放器一樣可以播放該視頻。

那么就是說,我們可以通過讀取文件內容,來具體識別出文件類型。

原理在此簡單介紹下,其實在每個文件生成時,都會有個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是完全一樣的。

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

 本文由用戶 jklikhjk 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!