举例 docx格式直接改后缀成pdf,upload无法判断问题

修修upload吧

最近做的项目使用到upload,需要满足既可以上传图片又可以上传pdf且需要能预览。

最开始霹雳吧啦一顿操作,写完了,如下:

  const beforeUpload = (typeI, file) => {
    const { name, size } = file;
    const myType = name.slice(name.indexOf('.') + 1);
    const isJpgOrPng = ['jpg', 'jpeg', 'png', 'bmp', 'pdf'].includes(myType);
    if (!isJpgOrPng) {
      message.error('上传格式不符合要求');
    }
    const isLt10M = size / 1024 / 1024 < 10;
    if (!isLt10M) {
      message.error('文件大小需要在10M以内');
    }
    return isJpgOrPng && isLt10M;
  }

思路就是上传时候能拿到文件名,做个判断就好了,轻轻松松。(typeI是多处使用自个做的标识)

测试测完了,项目经理提了个问题,说我把docx文件后缀改成pdf,上传成功了,但是预览出现问题了;嘴上怼了回去,哪有这样搞的,这样弄的电脑都不会操作吧,基本操作都不了解;心里开始琢磨怎么解决了,网上一顿输出找到了一版我也看不懂的操作,又自己东拼西凑了一版,如下:

第一种方式:这是做读取判断文件是否是对应的格式

  function readBuffer(file, start = 0, end = 2) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = () => {
        resolve(reader.result);
      };
      reader.onerror = reject;
      reader.readAsArrayBuffer(file.slice(start, end));
    });
  }
  function check(headers) {
    return (buffers, options = { offset: 0 }) =>
      headers.every(
        (header, index) => header === buffers[options.offset + index]
      );
  }
  function stringToBytes(string) {
    return [...string].map((character) => character.charCodeAt(0));
  }
  async function handleChange(file) {
    const isPNG = check(stringToBytes("%PDF")); // 决定进行哪种文件判断
    const buffers = await readBuffer(file, 0, 8);
    const uint8Array = new Uint8Array(buffers);
    return await isPNG(uint8Array);
  }```
  
第二种方式:原理就是通过FileReader读取文件,通过文件开头格式进行判断是否是对应的文件;
像修改文件类型,浏览器会将其对应的file.type也会随着更改,这种可以改为根据文件最后的后缀名进行判断。
但是碰上直接改文件后缀的不好使了啊。

```javascript
  const getFileMimeType = (file) => {
    const reader = new FileReader();
    reader.readAsArrayBuffer(file);
    return new Promise((resolve, reject) => {
      reader.onload = (event) => {
        try {
          let buffer = [...Buffer.from(event.target.result)];
          // 仅要文件的前四位就够了
          buffer = buffer.splice(0, 4);
          buffer.forEach((num, i, arr) => {
            arr[i] = num.toString(16).padStart(2, '0'); // 转成16进制且当不足两位数时在前头补个0
          });
          // 504b0304 是 xlsx 的文件头 16进制
          // 25504446 是 pdf 的文件头  16进制
          resolve(buffer.join('') === '25504446');
        } catch (e) {
          // 读取文件头出错 默认不是合法文件类型
          reject();
        }
      };
    });
  }
  const beforeUpload = (typeI, file) => {
      return new Promise(async (resolve, reject) => {
      const { name, size } = file;
      const myType = name.slice(name.indexOf('.') + 1);
      const isJpgOrPng = ['jpg', 'jpeg', 'png', 'bmp', 'pdf'].includes(myType);
       // const isPdf = await getFileMimeType(file);
      const isPdf = await handleChange(file);  // 调用上述方法符合的返回true,否则false
      if (myType == 'pdf' && !isPdf) {
        message.error('上传文件不是pdf格式文件');
        reject();
      }
      if (!isJpgOrPng) {
        message.error('上传格式不符合要求');
        reject();
      }
      const isLt10M = size / 1024 / 1024 < 10;
      if (!isLt10M) {
        message.error('文件大小需要在10M以内');
        reject();
      }
        resolve();
    })
  };

细心的小伙伴可能发现了,beforeUpload方法换写法了,用上了promise;因为getFileMimeType(file)handleChange(file)是异步函数。有人的会问怎么不用asyncawait了,实际大伙自个使用试试,原因我也不太清楚,会出现beforeUpload限制条件都失效了,onchange走了三遍;真的是很无奈啊,然后再看了下官网beforeUpload的使用,可以返回一个promise,那就改一下吧,成了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值