You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Vue 3中正确使用file-type库进行文件类型校验?

问题描述

我想借助file-type工具,同时通过文件扩展名和文件头信息校验文件合法性,但遇到版本兼容问题:在19.0.0版本中找不到fileFromFileType导出项,16.5.4版本里该函数也无法正常使用。

以下是我的实现代码:

<template>
  <div style="font: 13px Verdana; background: #eee; color: #333; margin: 2px; padding: 20px;">
    <h1>上传照片</h1>

    <div id="filelist">您的浏览器不支持Flash、Silverlight或HTML5。</div>
    <br />

    <div id="container">
      <a id="pickfiles" href="javascript:;">[选择文件]</a> 
      <a id="uploadfiles" href="javascript:;" @click="checkValidFile">[上传文件]</a>
    </div>
    <br />

    <pre id="console">{{ errorMessage }}</pre>
  </div>
</template>

<script>
import plupload from 'plupload';
import * as fileType from 'file-type';
export default {
  data() {
    return {
      uploader: null,
      errorMessage: ''
    }
  },
  mounted() {
    this.uploader = new plupload.Uploader({
      runtimes : 'html5,flash,silverlight,html4',
      browse_button : 'pickfiles',
      container: document.getElementById('container'),
      url : 'https://localhost:7104/api/PlUpload/File', 
      flash_swf_url : '../js/Moxie.swf',
      silverlight_xap_url : '../js/Moxie.xap',
      chunk_size:'5mb',
      max_retries: 100,

      filters : {
        max_file_size : '5gb',
        mime_types: [
          {title : "图片文件", extensions : "jpg,jpeg,gif,png"},
          {title : "视频文件", extensions : "mp4"}
        ]
      },

      init: {
      PostInit: () => {
        document.getElementById('filelist').innerHTML = '';
      },

      FilesAdded: (up, files) => {
        files.forEach(file => {
          document.getElementById('filelist').innerHTML += '<div id="' + file.id + '">' + file.name + ' (' + plupload.formatSize(file.size) + ') <b></b></div>';
        });
      },

      UploadProgress: (up, file) => {
        document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = '<span>' + file.percent + "%</span>";
        if (file.percent === 100) {
          this.errorMessage = '';
        }
      },

      ChunkUploaded: (up, file) => {
        const delayBetweenChunks = 15; 
        setTimeout(() => {
          up.trigger('UploadProgress', file);
          up.trigger('BeforeUploadChunk', file);
        }, delayBetweenChunks);
      },

      Error: (up, err) => {
        if (err.code === plupload.HTTP_ERROR && err.status === 0) {
          this.errorMessage = '网络错误,请重新连接网络以恢复上传。';
        } else {
          this.errorMessage = '错误';
        }
      },  
    },
      
    });

    this.uploader.init();
  },
  methods: {
    selectFiles() {
      this.uploader.start();
    },

    generateUniqueIdentifier() {
      const timestamp = Date.now();
      const randomString = Math.random().toString(36).substring(2, 15);
      return `${timestamp}-${randomString}`;
    },

    uploadFiles() {
      this.uploader.start();
    },

    async checkValidFile() {
      if (!this.uploader.files.length) {
        console.error('未选择文件。');
        return;
      }

      for(let i = 0; i< this.uploader.files.length; i++){
        let file = this.uploader.files[i];
        console.log(await fileType.fileTypeFromFile(file));
      }

    },
    
  }
}
</script>
解决方案

file-type不同版本的API差异较大,需对应版本使用正确方法:

适配file-type v16.x版本

v16.x无fileTypeFromFile方法,需读取文件Blob数据,用fromBlob检测:

修改checkValidFile方法:

async checkValidFile() {
  if (!this.uploader.files.length) {
    console.error('未选择文件。');
    return;
  }

  for(let i = 0; i < this.uploader.files.length; i++){
    const pluploadFile = this.uploader.files[i];
    // 将plupload文件转为Blob
    const blob = await new Promise((resolve) => {
      pluploadFile.getSource(false, (source) => {
        resolve(source.blob);
      });
    });
    // 检测文件类型
    const result = await fileType.fromBlob(blob);
    console.log(result);
    
    // 校验扩展名与文件头是否匹配
    const fileExt = pluploadFile.name.split('.').pop().toLowerCase();
    if (!result || result.ext !== fileExt) {
      this.errorMessage = `文件${pluploadFile.name}格式不合法,请检查文件类型`;
      return;
    }
  }
  
  // 校验通过后启动上传
  this.uploader.start();
}

适配file-type v19.x版本

v19.x需使用fromFile方法,该方法接收原生File对象,需先转换plupload文件:

修改checkValidFile方法:

async checkValidFile() {
  if (!this.uploader.files.length) {
    console.error('未选择文件。');
    return;
  }

  for(let i = 0; i < this.uploader.files.length; i++){
    const pluploadFile = this.uploader.files[i];
    // 转换为原生File对象
    const nativeFile = await new Promise((resolve) => {
      pluploadFile.getSource(false, (source) => {
        resolve(new File([source.blob], pluploadFile.name));
      });
    });
    // 检测文件类型
    const result = await fileType.fromFile(nativeFile);
    console.log(result);
    
    // 校验扩展名与文件头是否匹配
    const fileExt = pluploadFile.name.split('.').pop().toLowerCase();
    if (!result || result.ext !== fileExt) {
      this.errorMessage = `文件${pluploadFile.name}格式不合法,请检查文件类型`;
      return;
    }
  }
  
  // 校验通过后启动上传
  this.uploader.start();
}

注意事项

  • 安装对应版本后,务必确认官方文档的API规范,避免版本不兼容问题
  • plupload文件需通过getSource方法获取Blob数据,再转换为对应格式用于检测
  • 校验时需同时对比检测出的扩展名和文件名扩展名,防止篡改扩展名的非法文件

内容的提问来源于stack exchange,提问作者Seppe OK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 05:54:56