一、为什么需要限制文件类型
在前后端交互的过程中,我们经常需要上传和下载文件。但是文件类型有可能是恶意文件,例如:病毒、木马等。限制文件类型可以避免恶意文件的上传和下载,保证网站的安全。
二、前端限制文件类型的方式
前端根据不同浏览器的API,可以通过以下方式来限制文件类型:
1、设置文件类型的accept属性
accept属性控制文件选取对话框只弹出指定类型文件,但是用户仍然可以通过修改文件扩展名来绕过验证,所以需要在后端再次验证文件类型。
2、使用FileReader对象读取文件类型
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = () => {
const result = reader.result;
const arr = new Uint8Array(result);
const header = [];
for (let i = 0; i < arr.length; i++) {
header.push(arr[i].toString(16));
}
const fileType = getFileType(header.join(''));
};
reader.readAsArrayBuffer(file);
function getFileType(head) {
switch (head) {
case '89504e47':
return 'image/png';
case '47494638':
return 'image/gif';
case '25504446':
return 'application/pdf';
default:
return 'unknown';
}
}
使用FileReader对象读取文件,获取文件的字节流,根据字节流的前几位,判断文件类型。但是这种方式只能读取文件的前几个字节,可能存在误判,需要后端再次验证。
三、后端限制文件类型的方式
后端也需要对文件类型进行验证,避免绕过前端验证的恶意文件被上传。
1、使用mime类型判断文件类型
const fs = require('fs');
const fileType = require('file-type');
const file = fs.readFileSync('/path/to/file');
const mime = fileType(file).mime;
if (!/^(image\/|video\/|audio\/)/.test(mime)) {
console.log('文件类型错误');
}
使用file-type插件获取文件的mime类型,根据mime类型判断文件类型是否符合规定。缺点是文件没有扩展名时无法判断。
2、使用扩展名判断文件类型
const path = require('path');
const extname = path.extname('/path/to/file');
if (!/^(.jpg|.jpeg|.png)$/i.test(extname)) {
console.log('文件类型错误');
}
通过文件的扩展名判断文件类型是否符合规定。但是扩展名是可以被修改的,所以需要结合mime类型验证。
四、总结
前后端都需要对文件类型进行验证,可以通过accept属性、FileReader对象、mime类型、扩展名等方式进行验证。建议采用多种方式结合,提高验证的准确性。