当前位置: 首页 > 工具软件 > inputfile > 使用案例 >

Web前端 input file 文件上传优化

唐照
2023-12-01

前言:

在Web开发过程中,当项目做得越来越大时,文件上传功能也会被使用得非常多,之前项目经理反馈一个问题,就是当点击[选择上传文件]按扭时,弹出文件浏览框总是很慢,点击上传按扭后,要很久文件选择窗口才能弹出来,经过一翻折腾,后来发现是因为input file类型的标签中 没有限制指定可上传的文件类型 accept=“*” (默认全部类型)

所以它会检索全部类型,从而导致在弹出文件选择窗口时慢的问题。
然而,在HTML5中使用 input file控件 选择上传文件的时候,根据需要可限制指定的文件类型(默认任意类型 )。在 input type=“file” 加上 accept="指定要上传的文件类型"即可。

更多MIME类型:
参见1:https://www.w3school.com.cn/media/media_mimeref.asp
参见2:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME_types

文件类型( accept属性) :

例如:

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

accept属性常见配置:(如果不加accept属性,则上传任意类型的文件[默认])


accept=".doc, .docx, .xls, .txt" // 只能上传word, exls, .txt文件
accept=".rar, .zip" // 只能上传压缩文件
accept=".mp3" // 只能上传mp3文件
accept=".mp4, .avi, .swf, .mpeg" // 只能上传视频文件
accept=".jpg, .jpeg .png, .gif, .bmp" // 只能上传指定的这些图片文件
accept="image/*" // image表示图片,*表示所有支持的格式, video/* video表示视频,*表示所有支持的格式

注意:如想要真正的限制用户只能上传某些类型的文件,用accept属性来做限制是没用的!!

因为:用户可以随意的修改文件的后缀名(扩展名)

所以:想要真正的限制用户只能上传某些类型的文件,

  1. 让后端帮助做文件类型判断(不推荐)。
  2. 前端自己用JS new FileReader() 读取到 上传文件的二进制头信息来判断文件类型因为,不同类型的文件,各类文件的二进制头信息是不一样的,所以,即便是用户修改了文件的后缀名,但文件的二进制头信息不是会变的
  3. 根据文件的二进制头信息来判断文件类型的具体实现方法可以参考这篇博文:https://blog.csdn.net/muguli2008/article/details/122205234

文件数量( multiple属性) :

HTML5中的input type="file"在选择上传文件的时候,根据需要可限制选择 1个 或 多个 文件。在 input type=“file” 加上 multiple 属性 即可!

例如:

<input type="file" id="oFile" name="myFiles" multiple onchange="upFile(event)" />

扩展1:

1、上传时可以同进选多个文件( multiple 属性 ):
想要在上传时可以同进选多个文件,只需要在 input标签中加上 multiple 属性 就可以多选啦!多选的方式:可按住鼠标左键拖动进行多选,或按下键盘上的Ctrl键,或 Shitf键 再鼠标左键点选,或 Ctrl + A 全选。

注意: 默认情况下一般都没加multiple 属性,所以只能选择1个文件

最后:如果以上两种情况都要用到时,就同时加上 multiple属性 和 accept="指定要上传的文件类型"属性即可!

例如:

<input type="file" id="oFile" name="myFiles" multiple accept=".jpg, .jpeg .png, .gif, .bmp" onchange="upFile(event)" />

2、在JS中获取上传文件的相关属性
一般在文件上传,经常会做一些配置和限制如,文件的类型、大小等,可以在上传事件中获取到上传文件的相关属性。

function upFile(event) {
	const file = event.target.files[0] || event.dataTransfer.files[0] || this.file.files[0];
	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; 
    } 
	
	// 使用FormData方式上传,并设置相应的参数
	const fData = new FormData();
	fData.set("myFiles", file);  // 设置上传属性
	fData.set("myxxx", 'abcdef');  // 设置自定义上传参数
	fData.append("name", file.name);  // 添加上传信息
	fData.append("type", file.type);  // 添加上传信息
	fData.append("size", file.size);  // 添加上传信息
	fData.append("id", 666);    // 添加上传信息
}

3、上传图片文件时即时预览图片:
当然,最好的预览是在图片真正的上传成功后,根据后端API返回的图片文件URL是最为稳妥的,但是由于文件上传会有一定延时性等原因,所以为了提高用户体验,可以在用户点击上传的同时,先看到图片的预览效果,等到真正的上传成功后在无感的替换掉就OK啦。

function upFile(event) {
    const file = event.target.files[0] || event.dataTransfer.files[0] || this.file.files[0];
    // 图片预览1
    const createObjectURL =  window.createObjectURL || window.URL.createObjectURL || window.webkitURL.createObjectUR;
    console.log(createObjectURL(file)));
	
	// 图片预览2
	const fr = new FileReader();
	fr.readAsDataURL(file); // Base64 8Bit字节码
    // fr.readAsBinaryString(file);  // Binary 原始二进制
    // fr.readAsArrayBuffer(file);   // ArrayBuffer 文件流
	fr.onload = function(res) {
		console.log(this.result);
		console.log(res.target.result);
		console.log(res.srcElement.result);
	};
	
	// 注意:当第二次再次选择之前的那个文件后,onchange事件不触发,所以要清空一下value
	if (event.target.outerHTML) {
		event.target.outerHTML = event.target.outerHTML;
    } else {
		event.target.value = '';
	};
}

4、上传时如何判断文件的大小:
上传时在JS中通过event对象下的target属性,就可以获取当前上传文件的大小啦!
但是:由于在上传时文件的单位是以字节(Byte)为单位,所以需要做一下转换。

function upFile(event) {
    const file = event.target.files[0] || event.dataTransfer.files[0] || this.file.files[0];
    
    console.log((file.size / 1024 ).toFixed(2)); // KB;
    console.log((file.size / 1024 / 1024).toFixed(2); // MB;
    console.log((file.size / 1024 / 1024 / 1024).toFixed(2)); // GB;
	
	// 限制文件大小在500KB以内
	if(file.size / 1024 > 500){ 
    	alert('对不起:上传的文件不能大于500KB'); 
    	return false; 
    }
    
    // 限制文件大小在2MB以内 
    if(file.size / 1024 / 1024 > 2){ 
    	alert('对不起:上传的文件不能大于2MB'); 
    	return false; 
    }
    
	// 还可以用乘法来计算上传文件大小
    	1KB = 1 * 1024;
    	1MB = 1 * 1024 * 1024;
    	1GB = 1 * 1024 * 1024 * 1024;
   
	// 限制文件大小在3MB以内 
	if(file.size > 3 * 1024 * 1024){ 
    	alert('对不起:上传的文件不能大于3MB'); 
    	return false; 
    }
    
	/* 其他: 文件上传进度 的 百分比计算公式:
	 	event.loaded 文件已上传的大小
	 	event.total 文件的总大小
	 	progress = 100 * event.loaded / event.total;
	*/
	 progress = (100 * event.loaded / event.total).toFixed(2); // 保留2位小数

}

扩展二:

在计算机信息技术应用中,信息存储量是度量存储器存放程序和数据的数量。其主要度量单位是字节(Byte)
1个字节(Byte) 等于8位(bit)二进制。
位(bit,Binary Digits):是存放一位二进制数,即0或1,为最小的存储单位,8个二进制位为1个字节单位。
1个英文字母(不分大小写)占1个字节的空间,英文标点占1个字节。
1个中文汉字占2个字节的空间,中文标点占2个字节。

单 位说 明换 算
Bit(Bit,位)最小存储单位(二进制数,即 0 或 1)
Byte(Byte,字节)等于 8位(bit)
KB( Kilobyte,千字节)1KB( Kilobyte,千字节) = 1024B
MB( Megabyte,兆字节)1MB( Megabyte,兆字节) = 1024KB
GB( Gigabyte,吉字节,千兆)1GB( Gigabyte,吉字节,千兆) = 1024MB
TB( Trillionbyte,万亿字节,太字节)1TB( Trillionbyte,万亿字节,太字节) = 1024GB
PB( Petabyte,千万亿字节,拍字节)1PB( Petabyte,千万亿字节,拍字节) = 1024TB
EB( Exabyte,百亿亿字节,艾字节)1EB( Exabyte,百亿亿字节,艾字节) = 1024PB
ZB(Zettabyte,十万亿亿字节,泽字节)1ZB(Zettabyte,十万亿亿字节,泽字节) = 1024EB
YB( Yottabyte,一亿亿亿字节,尧字节)1YB( Yottabyte,一亿亿亿字节,尧字节) = 1024ZB
BB( Brontobyte,千亿亿亿字节)1BB( Brontobyte,千亿亿亿字节) = 1024YB
 类似资料: