美文网首页
js获取文件真实类型

js获取文件真实类型

作者: 头上有煎饺 | 来源:发表于2022-02-07 15:32 被阅读0次

    1. 方法简介

    方法一:
    最简单的就是直接获取文件后缀,但是如果后缀不准确,被人为修改就会出现识别错误
    方法二:
    直接读取文件二进制信息头部获取类型。

    2. 实现

    2.1 原理

    在计算机里面,所有文件本质都是一对二进制数据,而各种文件类型除了给用户看的后缀用以区分,本身二进制数据里面也有用于区分类型的数据。大部分文件二进制头部都有用于区分其类型的一串特征编码,也就是一串神奇数字。
    比如png头部前8个字节是0x89504E470D0A1A0A,我们只要读取出前八个字节就可以基本上确定这就是一个png无论你把它后缀改成什么。(字节数搞不清楚的可以单独去网上查一下,简单说一下,这里是16进制,大部分计算机4位等于116进制,8位为1字节,所以这里有1616进制也就是8个字节)

    2.2 TypedArray实现

        <input id='file' type="file"/>
        <script>
            // 输入事件
            document.getElementById('file').onchange = function (e) {
               // 获取文件
               const file = this.files[0]
               // 读取文件二进制内容
               // arrayBuffer存储的是字节为单位的数据
               // arrayBuffer直接是不能做什么操作的,所以要转换一下
               file.arrayBuffer()
                   .then(arrayBuffer => {
                     // 二进制转化为数字
                     // 先提取头部8个字节
                     // 后面我们要每8位转化成一个数字
                     // 你用Uint16Array也可以,但是不大好比较,因为大部分计算机的字节序都是小端,所以每一段顺序是反的,不好比较
                     const flieUnit8Array = new Uint8Array(arrayBuffer.slice(0, 8))
                     // 输出一个类似数组的 [ 137, 80, 78, 71, 13, 10, 26, 10 ]
                     // 你可以试一试Uint16Array,你会发现顺序反了 [ "5089", "474e", "a0d", "a1a" ]
                     const checkList = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]
                     // 对位比较就行了
                     console.log(unit8.every((v, index) => v === checkList[index]))
                  })
            }
      </script>
    

    2.3 DataView实现

        <input id='file' type="file"/>
        <script>
            document.getElementById('file').onchange = function (e) {
               const file = this.files[0]
               file.arrayBuffer()
                   .then(arrayBuffer => {
                      // 前面都是一样的,这里我们把arrayBuffer 转成dataView
                      // dataView仍然是一堆字节
                      const dataView = new DataView(arrayBuffer.slice(0, 8))
                      // 接下来不需要转化成数字,直接调用dataview的方法就行了
                      const checkList = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]
                      checkList.every((v, index) =>  v === dataView.getUint8(index)) // true 
                      // 这里不同的是我们取16位的整数顺序正确了
                      ['0x8950', '0x4e47', '0xd0a', '1a0a'].every((v, index) =>  v === dataView.getUint16(index)) // true 
                  })
            }
      </script>
    

    3 总结

    1. 大部分时候直接判断后缀就行了,如果需要严格判断就可以使用这种方法
    2. 最好使用8位的转化方法,防止某些平台字节序的不同导致判断失败

    相关文章

      网友评论

          本文标题:js获取文件真实类型

          本文链接:https://www.haomeiwen.com/subject/ohymkrtx.html