IT技术博客大学习 共学习 共进步

Web前端文件处理

Hito's Blog 2016-03-21 23:51:06 浏览 1,381 次

   在项目中,我们经常会有这样的需求,对上传的文件大小进行限制,传统的做法是在服务器端进行大小限制,例如nginx通过client_max_body_size,php.ini中可以通过upload_max_filesize和post_max_size来设置上传的文件大小。这种做法的缺陷很明显,数据上传到服务器之后,再对其进行监测,大大增加了宽带和服务器的压力。何不放在客户端进行检测?

   在IE10及以下的版本,可以通过如下方式检测需要上传文件的大小:

<input type="file" onchange="checksize()">
<script>
function checksize(e){
	var ev = e || window.event;
	var uri =  ev.srcElement.value;
	var img = new Image();
	img.onload=function(){
		alert("文件大小为"+(img.fileSize)/1024+"KB");
	}
	img.src=uri;
}
</script>

   上面的代码的运行原理是把上传的文件模拟成图片,通过其fileSize属性获取其大小,而由于浏览器的安全策略,其几乎只能运行在本地打开此网页的情况。加上微软在IE11上已经废除了fileSize的属性1,而现代浏览器厂商为了保护本地操作系统,在用户上传文件的时候,本地资源路径一律采用fakepath2,更加阻止了这种方法获取文件大小的可行性。

   HTML5 File API

   在HTML4时代,浏览器几乎是不提供本地文件操作API的,而HTML5给了开发者更大的自由,不仅支持获取上传文件大小,还支持多文件同时上传:

<input type="file" multiple="multiple" onchange="checkinfo(this)">
<script>
function checkinfo(obj){
	var len = obj.files.length;

	var text="";
	for (var i =0 ; i < len ; i++){
			text += "文件:"+obj.files[i].name+" ,大小:"+obj.files[i].size+"字节\n";
	}
	console.log(text);
}
</script>

   在file类型的input中增加multiple属性,即可上传多个文件,而不必通过增加input框的个数来增加上传文件数量的限制。而对于file类型的对象,HTML5增加了一个FileList接口,让访问<input type="file">元素选中的文件列表成为可能,它还可以应用于用drag和drop API获取拖拽到web页面的文件列表。它有item, length等属性。更加详细的介绍,可以点击这里

   利用HTML5,不仅可以获取文件大小,还可以进行本地的图片预览:

<input type="file" multiple="multiple" onchange="checkinfo(this)">
<div id="win"></div>
<script>
function checkinfo(obj){
	var len = obj.files.length;
	for (var i =0 ; i < len ; i++){
			showimg(obj.files[i]);
	}
}

function showimg(img){
	var a = new FileReader();
	a.readAsDataURL(img);
	a.onload=function(){
		var img = new Image();
		img.src=a.result;
		document.getElementById('win').appendChild(img);
	}
}

</script>

   这里用到FileReader这个文件API,它可以让web应用异步加载本地的文件或者内容,它用来操作File或者Bob对象,它的详细介绍,可以点击这里。有了FileReader对象,我们就可以完成很多以前不能在前端完成的事情。如,web前端图片大小截取:

<input type="file" multiple="multiple" onchange="checkinfo(this)">
<div id="win"></div>
<script>
function checkinfo(obj){
	var len = obj.files.length;
	for (var i =0 ; i < len ; i++){
			showimg(obj.files[i]);
	}
}

function showimg(img){
	var a = new FileReader();
	a.readAsDataURL(img);
	a.onload=function(){
		var img = new Image();
		img.src=a.result;
		document.getElementById('win').appendChild(img);
		big2small(a.result);
	}
}

function big2small(){
	var img = document.getElementsByTagName("img")[0];
	var iwidth=img.width;
	var iheight=img.height;
	var canv = document.createElement('canvas');
	var cvx = canv.getContext("2d");
	var x = window.prompt("请输入起点X坐标");
	var y = window.prompt("请输入起点y坐标");
	var wi = window.prompt("请输入宽度");
	var he = window.prompt("请输入高度");
	cvx.drawImage(img,x,y,wi,he,0,0,wi,he);
	document.body.appendChild(canv);
}
</script>

   HTML5中前端文件处理的File API还为我们提供其它非常多的接口和灵活的运用,如上传进度提示,数据分段等,关于File APi的介绍,可以点击这里

参考资料

  1. fileSize property

  2. Google Group

  3. FileReader

建议继续学习

  1. QQ上传大文件为什么这么快 (阅读 13,082)
  2. 海量小文件存储 (阅读 9,702)
  3. 10个强大的Ajax jQuery文件上传程序 (阅读 8,721)
  4. 其实,文件也可以truncate (阅读 8,443)
  5. 解决securecrt rz 上传rar,gif文件不正确问题 (阅读 7,781)
  6. PHP上传进度条深度解析 (阅读 5,921)
  7. 关于Linux的文件系统cache (阅读 5,822)
  8. Perl 倒行分析文件方法。perl读文本文件,从末尾往前读. (阅读 5,505)
  9. Codeigniter里的无刷新上传 (阅读 5,421)
  10. C/C++循环获取文件中的每行数据(别以为很简单!) (阅读 5,103)