DAY17 - 档案处理 - 不只是副档名检查!真正的检查档案格式

通常上传档案时,严谨一点,可能会需要做「档案格式检查」。
白话一点说,就是使用者上传的档案有没有符合网站限制的格式
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


<<:  Docker:Docker Hub Pull 流程

>>:  18 程序竞赛前中後准备实例 (NCPC 2021)

[Day28] 介绍 CRUD

哈6夥伴们,这一路下来说明了一些简单的API,不知道夥伴们有没有发现,其实有些函式是常常使用的呢~~...

[DAY-18] 我在这里帮忙 把人类送上月球

前前行提要: 找出你珍视的机会 前行提要: 热情从何处来 炉边撰杜选小故事 当甘乃迪总统造访 火箭发...

Day 25: Behavioral patterns - State

目的 如果物件内的方法,会依据物件内的状态,使用多个 if - else if - else 或 s...

Angular#4 专案:路由 建置

Angular [目标] 启动程序先导入Login元件 1. 新增元件、模组 Syntax:ng h...

Day11 为什麽电脑能自动完成指令 - Lua 的多值回传

从前几回的研究中,我已经学会 Lua 的函数宣告,也只是一个 function 变数,以及相关的语法...