如何在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
相关产品推荐
相关产品推荐

