背景:项目里有个简单的要求,有个表单要上传图片,但在尺寸大小上有所限制,原谅我总是用插件,我这次用了IVIEWUI,发现UpLoad组件只有对占内存大小进行限制。于是不得不靠度娘,谷哥等。经过一番收集,发现几种不错的方案。
首先,是“canvas”压缩大法!
这个方法有个最大的好处就是不管用户上传什么图片,最后传到服务器都能变成某个范围大小的图片,几乎不用用户做什么,可谓体验良好。当时看了第一眼就觉得很不错,用它来实现需求既能学习到东西还增进体验。
这个方法的核心在 canvas 的 drawImage() 。参数格式如下:
context.drawImage(img, dx, dy);
context.drawImage(img, dx, dy, dWidth, dHeight);
context.drawImage(img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
整体思路是:在input监听change事件,然后用FileReader API和生成Image实例来读取以及对图片尺寸大小判断或处理,在Image实例的onload回调里执行canvas的drawImage()方法。
这样说可能有点模糊,这是因为后来这个方法被否定了,不是有更牛的的方法,纯属因为后端工作比我快,相关的接口已经写好,只接受file文件即原图片,而由canvas生成的图片无论是base64还是用toBlob()方法传到后端都没用。无奈,只好放弃!但这个方法是从张鑫旭大佬那里看到,这里倒也可以附上链接:
HTML5 file API加canvas实现图片前端JS压缩并上传www.zhangxinxu.com然后另一种方法,只能是直接限制大小,其实这个方法还是借鉴了上面的例子。
既然可以通过FileReader和Image能生成<img>的元素,那么自然可以通过正常的JS操作来获取图片尺寸大小进行限制,不过要求本来就简单,是我想做难了!取一截代码段来记录下,该代码段是绑定在VUE的一个input[type=file]的change事件上的。
let
限于技术和时间可能写的不好,但基本功能却也符合要求,只能说以后再看本文章能不能勾起兴趣取深究下。
多张图片上传
关于这个问题,其实直接用插件处理会很简单而且某个方面来说会更安全(要么不出错要么出错了可以甩锅给插件作者)。
不过,我这次倒是用了原生的写,主要是因为:
1.原声我可以更方便自定义样式,这个占很大原因
2.老是调用插件,我不太明白原来的input[type=file]作用有多少
3.我选的插件是iview的upload组件,在上传时,多传图片会变为单图多次上传,基于上面的某个理由,我又得自己写。
图片多传的关键属性是multiple,在input的change事件里会得到一个文件列表,不过我不打算添加action属性,我打算用axios把图片发送给后端,这就扯到另一个有趣的东西——FormData()。这个方法会模拟表单上传,用法大概类似:
var fd = new FormData();
fd.append(key,value);
至于为什么要模拟成表单提交,嗯~ o(* ̄▽ ̄*)o!!后端写的快,进度又赶,技术又菜只好按别人规定的来写呗!对了,这个还需要设置头部"headers"为"multipart/form-data"来搭配使用。
同样截取代码段来记录下,以后估计还有用,还能以此完善:
handleBeforeUpload
这里有个小插曲,遍历获取的文件列表时,我本想用foreach来做个判断,如果某个图片大小超出规定就会跳出循环直接结束,但我好像跳不出来,只好使用了for循环。
最后来个总结小心得:
本来在写之前还以为自己能写出不少东西,毕竟fileReader,canvas,以及input[type=file]的change事件里的filelist的各种属性都可以研究。只是写起来发现不太容易,这会脱离我原本想讲的东西而且我学的没这么多,说多了就是误导,只能写出一点玩意勉励自己。