iT邦幫忙

2021 iThome 鐵人賽

DAY 17
0
Modern Web

不只是串串API,新手前端30天系列 第 17

DAY17 - 檔案處理 - 不只是副檔名檢查!真正的檢查檔案格式

  • 分享至 

  • xImage
  •  

通常上傳檔案時,嚴謹一點,可能會需要做「檔案格式檢查」。
白話一點說,就是使用者上傳的檔案有沒有符合網站限制的格式
EX:我們要求這個檔案必須是圖檔的png或jpg。

那檔案格式要怎麼檢查呢,你是不是覺得檢查副檔名就好了,這有什麼好寫一天的~~~ nonono這樣你是很容易被騙的!今天我們就要介紹怎麼樣真正的檢查

  • 範例一樣以vue.js為例喔!

WAY1 普羅大眾的副檔名檢查

作法流程

透過副檔名檢查是否為限制的檔案格式。一般就是會透過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
    },
    ...

Demo畫面

sample code: 連結

這樣做就可以了嗎?這種方法其實就是防君子不防小人(?)的方法。
如果大家都乖乖地照原本這個檔案副檔名是什麼直接上傳,當然都不會有問題。但如果今天上傳的不是君子,小人傳了一個jpg檔案後,發現上傳檔案出現了錯誤,告訴他你必須要傳一個bmp的圖檔檔案。於是小人就把這個檔案修改名稱,在.的後面改成bmp。在上傳一次~ 可以試試看,這個檔案就被這個簡單的偷天換日,file檔案裡的type被成功騙過,變成bmp的格式了!!!!

於是,我們要介紹第二種方式,不讓你騙的檔案格式檢查法~~


WAY2 不讓你騙的檔案格式檢查法

因為每個檔案格式其實都有他的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));


    }
    ...

Demo畫面

sample code: 連結


透過真正的讀取檔案,對照file signature 就可以得到真正的檔案格式囉!今天大功告成XD


上一篇
DAY16 - 檔案處理 - 上傳前預覽
下一篇
DAY18 - 檔案處理 - 上傳檔案前需要知道的FormData
系列文
不只是串串API,新手前端30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言