1. 程式人生 > 程式設計 >JavaScript 檢測檔案的型別的方法

JavaScript 檢測檔案的型別的方法

我們會想到通過 input 元素的 accept 屬性來限制上傳的檔案型別:

<inputtype="file"id="inputFile"accept="image/png"/>

這種方案雖然可以滿足大多數場景,但如果使用者把 JPEG 格式的圖片字尾名更改為 .png 的話,就可以成功突破這個限制。那麼應該如何解決這個問題呢?其實我們可以通過讀取檔案的二進位制資料來識別正確的檔案型別。在介紹具體的實現方案前,阿寶哥先以圖片型別的檔案為例,來介紹一下相關的知識。

一、如何檢視圖片的二進位制資料

要檢視圖片對應的二進位制資料,我們可以藉助一些現成的編輯器,比如 Windows 平臺下的 WinHex 或 macOS 平臺下的 Synalyze It! Pro 十六進位制編輯器。這裡我們使用 Synalyze It! Pro 這個編輯器,以十六進位制的形式來檢視阿寶哥頭像對應的二進位制資料。

JavaScript 檢測檔案的型別的方法

二、如何區分圖片的型別

計算機並不是通過圖片的字尾名來區分不同的圖片型別,而是通過 “魔數”(Magic Number)來區分。 對於某一些型別的檔案,起始的幾個位元組內容都是固定的,根據這幾個位元組的內容就可以判斷檔案的型別。

常見圖片型別對應的魔數如下表所示:

檔案型別 檔案字尾 魔數
JPEG jpg/jpeg 0xFF D8 FF
PNG png 0x89 50 4E 47 0D 0A 1A 0A
GIF gif 0x47 49 46 38(GIF8)
BMP bmp 0x42 4D

同樣使用 Synalyze It! Pro 這個編輯器,來驗證一下阿寶哥的頭像(abao.png)的型別是否正確:

JavaScript 檢測檔案的型別的方法

由上圖可知,PNG 型別的圖片前 8 個位元組是 0x89 50 4E 47 0D 0A 1A 0A。當你把 abao.png 檔案修改為 abao.jpeg 後,再用編輯器開啟檢視圖片的二進位制內容,你會發現檔案的前 8 個位元組還是保持不變。但如果使用 input[type="file"] 輸入框的方式來讀取檔案資訊的話,將會輸出以下結果:

JavaScript 檢測檔案的型別的方法

很明顯通過 檔案字尾名或檔案的 MIME 型別 並不能識別出正確的檔案型別。接下來,阿寶哥將介紹在上傳圖片時,如何通過讀取圖片的二進位制資訊來確保正確的圖片型別。

三、如何檢測圖片的型別

3.1 定義 readBuffer 函式

在獲取檔案物件後,我們可以通過 FileReader API 來讀取檔案的內容。因為我們並不需要讀取檔案的完整資訊,所以阿寶哥封裝了一個 readBuffer 函式,用於讀取檔案中指定範圍的二進位制資料。

functionreadBuffer(file,start=0,end=2){
returnnewPromise((resolve,reject)=>{
constreader=newFileReader();
reader.onload=()=>{
resolve(reader.result);
};
reader.onerror=reject;
reader.readAsArrayBuffer(file.slice(start,end));
});
}

對於 PNG 型別的圖片來說,該檔案的前 8 個位元組是 0x89 50 4E 47 0D 0A 1A 0A。因此,我們在檢測已選擇的檔案是否為 PNG 型別的圖片時,只需要讀取前 8 個位元組的資料,並逐一判斷每個位元組的內容是否一致。

3.2 定義 check 函式

為了實現逐位元組比對並能夠更好地實現複用,阿寶哥定義了一個 check 函式:

functioncheck(headers){
return(buffers,options={offset:0}程式設計客棧)=>
&n程式設計客棧bsp;headheUzMvrVGwers.every(
(header,index)=>header===buffers[options.offset+index]
);
}

3.3 檢測 PNG 圖片型別

基於前面定義的 readBuffer 和 check 函式,我們就可以實現檢測 PNG 圖片的功能:

3.3.1 html 程式碼

<div>
選擇檔案:<inputtype="file"id="inputFile"accept="image/*"
onchange="handleChange(event)"/>
<pid="realFileType"></p>
</div>

3.3.2 js 程式碼

constisPNG=check([0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a]);// PNG圖片對應的魔數
constrealFileElement=document.querySelector("#realFileType");

asyncfunctionhandle程式設計客棧Change(event){
constfile=event.target.files[0];
constbuffers=awaitreadBuffer(file,8);
constuint8Array=newUint8Array(buffers);
reaheUzMvrVGwlFileElement.innerText=`${file.name}檔案的型別是:${
isPNG(uint8Array)?"image/png":file.type
}`;
}

以上示例成功執行後,對應的檢測結果如下圖所示:

JavaScript 檢測檔案的型別的方法

由上圖可知,我們已經可以成功地檢測出正確的圖片格式。如果你要檢測 JPEG 檔案格式的話,你只需要定義一個 isJPEG 函式:

constisJPEG=check([0xff,0xd8,0xff])

然而,如果你要檢測其他型別的檔案,比如 PDF 檔案的話,應該如何處理呢?這裡我們先使用 Synalyze It! Pro 編輯器來瀏覽一下 PDF 檔案的二進位制內容:

JavaScript 檢測檔案的型別的方法

觀察上圖可知,PDF 檔案的頭 4 個位元組的是 0x25 50 44 46,對應的字串是 %PDF。為了讓使用者能更直觀地辨別出檢測的型別,阿寶哥定義了一個 stringToBytes 函式:

functionstringToBytes(string){
return[...string].map((character)=>character.charCodeAt(0));
}

基於 stringToBytes 函式,我們就可以很容易的定義一個 isPDF 函式,具體如下所示:

constisPDF=check(stringToBytes("%PDF"));

有了 isPDF 函式,你就實現 PDF 檔案檢測的功能了。但在實際工作中,遇到的檔案型別是多種多樣的,針對這種情形,你可以使用現成的第三庫來實現檔案檢測的功能,比如 file-type 這個庫。

其實基於檔案的二進位制資料,除了可以檢測檔案的型別之外,我們還可以讀取檔案相關的元資訊,比如圖片的尺寸、位深度、色彩型別和壓縮演算法等,我們繼續以阿寶哥的頭像(abao.png)為例,來看一下實際的情況:

JavaScript 檢測檔案的型別的方法

好的,在前端如何檢測檔案型別就介紹到這裡。在實際專案中,對於檔案上傳的場景,出於安全考慮,建議小夥伴們在開發過程中,都限制一下檔案上傳的型別。對於更嚴格的場景來說,就可以考慮使用阿寶哥介紹的方法來做檔案型別的校驗。

以上就是javascript 檢測檔案的型別的方法的詳細內容,更多關於javaScript 檢測檔案的型別的資料請關注我們其它相關文章!