在项目中,我们经常会有这样的需求,对上传的文件大小进行限制,传统的做法是在服务器端进行大小限制,例如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,更加阻止了这种方法获取文件大小的可行性。
在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的介绍,可以点击这里。