通常上傳檔案時,嚴謹一點,可能會需要做「檔案格式檢查」。
白話一點說,就是使用者上傳的檔案有沒有符合網站限制的格式
EX:我們要求這個檔案必須是圖檔的png或jpg。
那檔案格式要怎麼檢查呢,你是不是覺得檢查副檔名就好了,這有什麼好寫一天的~~~ nonono這樣你是很容易被騙的!今天我們就要介紹怎麼樣真正的檢查
透過副檔名檢查是否為限制的檔案格式。一般就是會透過file裡面的type屬性拿到檔案格式;或者更直觀一點,直接以最後一個『.』為分割點,檢查檔案名稱中的副檔名是否符合限制。以下範例為透過file裡面的type屬性檢查檔案格式。
<div id="app">
<h5>Check Format</h5>
<input type="file" @change="checkFormat">
<p>File Format Type: {{type}}</p>
</div>
...
checkFormat(e) {
const _self = this;
let [file] = e.target.files;
_self.type = file.type
},
...
sample code: 連結
這樣做就可以了嗎?這種方法其實就是防君子不防小人(?)的方法。
如果大家都乖乖地照原本這個檔案副檔名是什麼直接上傳,當然都不會有問題。但如果今天上傳的不是君子,小人傳了一個jpg檔案後,發現上傳檔案出現了錯誤,告訴他你必須要傳一個bmp的圖檔檔案。於是小人就把這個檔案修改名稱,在.的後面改成bmp。在上傳一次~ 可以試試看,這個檔案就被這個簡單的偷天換日,file檔案裡的type被成功騙過,變成bmp的格式了!!!!
於是,我們要介紹第二種方式,不讓你騙的檔案格式檢查法~~
因為每個檔案格式其實都有他的File Signature,意思就是特定的檔案格式,他的File Signature是有固定規則可以依循的。
因此,我們可以透過File Signature來確認真正的檔案格式。
File Signature List --> 連結
以jpg或png為例,file signature就可以參照第一個欄位
step1. 選取檔案後,擷取前4個byte為了之後與file signature比對
step2. 檔案讀取並轉換成arrayBuffer的形式
step2. 轉換成 Uint8Array 並透過 toSting轉換成16進位
step4 並與file signature比對,即可知道真正的檔案格式
<div id="app">
<h5>Check Format</h5>
<input type="file" @change="checkFormat">
<p>Extention : {{extention}}</p>
<p>File Format Type: {{type}}</p>
</div>
...
//檢查16進制與file signature對照
covertFormat(val) {
console.log('checkFormat', val);
let type = '';
switch (val) {
case "89504e47":
type = "image/png";
break;
case "ffd8ffdb":
case "ffd8ffe0":
case "ffd8ffee":
case "ffd8ffe1":
type = "image/jpeg";
break;
default:
type = "others"; // Or you can use the blob.type as fallback
break;
}
return type;
},
//選取檔案後轉換
checkFormat(e) {
const _self = this;
let [file] = e.target.files;
_self.extention = file.type; //副檔名的format
let reader = new FileReader();
reader.onloadend = function (e) {
console.log('result', e.target.result)
let result = new Uint8Array(e.target.result);
let header = '';
for (var i = 0; i < result.length; i++) {
header += result[i].toString(16);
console.log('')
}
_self.type = _self.covertFormat(header); //真正的format
console.log('real Format:' + _self.type);
} //end: onloaded
reader.readAsArrayBuffer(file.slice(0, 4));
}
...
sample code: 連結
透過真正的讀取檔案,對照file signature 就可以得到真正的檔案格式囉!今天大功告成XD