问题复现:
搜狗浏览器部分电脑上传文件后文件类型 file.type 为空 (组件上传用的 ElementUI)
思路:
虽然没有文件类型但是有file文件整个可以通过转换文件为ArrayBuffer 来获取文件头分析文件类型具体请看File Signatures
具体代码:
1.安装file-type库
npm install file-type --save-dev
2.判断返回回调类型是否为空再做处理
const beforeUploadFn = async (file: any) => {
const isSize = file.size / 1024 / 1024 < 200;
try {
let fileData = file;
// 如果浏览器取不到类型自行判断
if (!file.type) {
const blob = await new Blob([file]); // 将file对象转为blob 下面会赋值到新的file中
const buffer = await blob.arrayBuffer(); // 将blob 转为ArrayBuffer
const typeFile = await fileTypeFromBuffer(buffer); // 通过file-type库判断 buffer头文件从而得出文件类型
// 创建新File对象并赋值
fileData = new File([blob], file.name, {
type: typeFile?.mime,
lastModified: file.lastModified
});
}
emit('beforeUploadFn', fileData);
if (!allowedTypes.includes(fileData.type)) {
ElMessage.error('请上传word,ppt,mp4,excel,jpg,png格式的文件!');
return false;
}
if (!isSize) {
ElMessage.error('文件大小不能超过200M!');
return false;
}
} catch (err) {
console.log(err);
}
};
注意:
1. 原始的file对象是不可更改的所以需要new 一个 新的File对象进行保存
2.file-type库中有很多方法但是 fileTypeFromBuffer 这个方法是最稳妥的 其他的方法本人也试过但是会有报错的API不支持的情况例如:fileTypeFromStream 报错为
这也可能是为什么 file.type 为空的终极问题 百度后得出可能部分浏览器所有node版本不一致导致API不支持
3. file转bolb后不可截取数组头部,会影响file-type判断类型截取后的ppt word 等格式会变成application/zip 类型所以不要自己手动截取2进制前面的头部 (猜测是 file-type bug)