前言

在Web项目开发过程中,文件上传功能几乎必不可少的,很多时候,我们在进行文件上传时,尤其是向普通用户开放文件上传功能时,一般都需要对上传文件的格式进行一些限制,以防止不良用户、黑客等将带有病毒脚本文件上传到服务器中,常见文件格式限制如下。

1、通过input标签的accept属性进行限制

我们可以通过HTML5中的 input file 标签的accept属性,根据自己的需求,在选择上传文件的时候,指定可见的文件类型格式(默认任意类型 )来进行限制。

实例代码:


<input type="file" id="oFile" name="myFiles" accept=".doc, .docx, .xls, .txt" onchange="upFile(event)" />

2、通过JS获取上传文件的file.type 或 file.name属性进行限制

在JS中,可以在上传事件中,通过file对象获取到上传文件的相关属性。

实例代码:


function upFile(event) {
	const [ file ] = event.target.files || event.dataTransfer.files || this.file.files;
	
	console.dir(file); // 文件对象
	console.log(file.name); // 文件名称  
	console.log(file.type); // 文件类型
    console.log(file.size); // 文件大小
	
	// 对文件类型做简单限制:如:只允许上传 jpg  png gif 这3种格式
	if(!file.type && /\.(?:jpg|png|gif)$/.test(file.name)) ){ 
	    alert('对不起:上传的图片格式只能是:jpg, png, gif 格式!'); 
    	return false; 
    } 
}

以上两种方式是我们最常见的文件上传类型限制方法,但是,如果单纯的以文件后缀名(扩展名)、文件类型进行截取的方式来进行限制,是非常容易遭到破解的,比如,用户要将文件的后缀名(扩展名),重命为你指定的可上传的文件类型,就绕过了你的限制,便可以完成上传。

此时:我们根据文件的头信息,来判断文件真正的格式。

3、通过JS的FileReader方法获取上传文件的头信息进行限制

在JS中通过读取文件的十六进制的头信息,来进行限制,因为相同类型文件的文件头信息是相同的,即使用户修改了文件的后缀名(扩展名),但文件的头信息是不会改变的。

实例代码:

// 读取文件的二进制数据并将其转换为十六进制
function fileReader (blob) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsBinaryString(blob);
    reader.onload = (ret) => {
      const res = reader.result.split('').map((o) => o.charCodeAt().toString(16).padStart(2, '0'));
      resolve(res.join(' ').toUpperCase());
    },
    reader.onerror = (err) => {
      reject(err);
    };
  });
};

// png格式
async function isPng(file) {
  return (await fileReader(file.slice(0, 8))) == "89 50 4E 47 0D 0A 1A 0A";
};

// jpg格式
async function isJpg(file) {
  const start = await fileReader(file.slice(0, 2));
  const end = await fileReader(file.slice(-2, file.size));
  return "FF D8" == start && "FF D9" == end;
};

// gif格式
async function isGif(file) {
  const ret = await fileReader(file.slice(0, 6));
  return "47 49 46 38 39 61" == ret || "47 49 46 38 37 61" == ret;
};

async function upFile(event) {
	const [ file ] = event.target.files || event.dataTransfer.files || this.file.files;
	
	console.dir(file); // 文件对象
	console.log(file.name); // 文件名称  
	console.log(file.type); // 文件类型
    console.log(file.size); // 文件大小
	
	// 根据文件头信息进行判断限制:如:只允许上传 png 这种格式
	if(!await isPng(file)){ 
	    alert('对不起:上传的图片格式只能是:png格式!'); 
    	return false; 
    }
}

4、通过第三方的file-type工具包来进行限制

file-type工具包也是用Js来进行封装的,其原理和上面的第3种方式一样,它支持的文件类型有几十种,几乎能满足我们的日常开发需求。

Npm地址:https://www.npmjs.com/package/file-type

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐