一、关于js上传图片压缩的方法,百度有很多种方法,这里我参考修改了一下
function photoCompress(file, w, objDiv) { var ready = new FileReader(); /*开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容.*/ ready.readAsDataURL(file); ready.onload = function() { var re = this.result; canvasDataURL(re, w, objDiv); } }; function canvasDataURL(path, obj, callback) { var img = new Image(); img.src = path; img.onload = function() { var that = this; // 默认按比例压缩 var w = that.width, h = that.height, scale = w / h; w = obj.width || w; h = obj.height || (w / scale); var quality = 0.5; // 默认图片质量为0.7 //生成canvas var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); // 创建属性节点 var anw = document.createAttribute("width"); anw.nodeValue = w; var anh = document.createAttribute("height"); anh.nodeValue = h; canvas.setAttributeNode(anw); canvas.setAttributeNode(anh); ctx.drawImage(that, 0, 0, w, h); // 图像质量 if(obj.quality && obj.quality <= 1 && obj.quality > 0) { quality = obj.quality; } // quality值越小,所绘制出的图像越模糊 var base64 = canvas.toDataURL('image/jpeg', quality); // 回调函数返回base64的值 callback(base64); } } function convertBase64UrlToBlob(urlData) { var arr = urlData.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); while(n--) { u8arr[n] = bstr.charCodeAt(n); } return new Blob([u8arr], { type: mime }); }
以上是压缩图片的方法,核心是将图片放入canvas内,再用canvas.toDataURL方法进行压缩,最后生成一个Blob对象。
注:因为牵扯到canvas,所以低版本浏览器应该是不支持的吧(有待考证)
二、图片压缩的方法有了,怎么使用呢?怎么上传到后台呢?往下看!
html部分:
<form action="file/uploadDoc" enctype="multipart/form-data" method="post"> <input type="file" /> <input type="submit" value="上传" /> </form>
js部分:
$("#file").change(function() { var formData = new formData("form"); var file = this.files[0]; photoCompress(file, { quality: 0.5, }, function(base64Codes) { var bl = convertBase64UrlToBlob(base64Codes); formData.set("file", bl, file.name); }); });
当选择文件以后,使用photoCompress方法对上传的图片进行压缩,photoCompress方法的第二个参数还可以传入长宽等参数,具体可以看photoCompress这个方法,quality是用来设置压缩后图片质量的,越小质量越差,表现出来就是图片越模糊,但是相应的体积就越小。
最后使用formData.set(key,value,name)方法,将现有的name为file的表单元素的值改变。这个方法有三个参数,第一个是key值,也就是表单里对应的元素的name值(如果不存在会自行添加),第二个值是value值,第三个是选填的值,如果第二个值为blob对象或者file对象,则第三个值表示文件名。
当然,如果你不想用form表单提交,你也可以用ajax提交的方法:
html:
<form enctype="multipart/form-data" method="post"> <input type="file" /> <input type="button" value="上传"/> </form>
有些许的变化,form没有了action,上传的按钮type改为了button
js部分给按钮添加一个点击事件,其他也没有变化,不做过多赘述:
$("#uploadBtn").click(function () { var formData = new formData("form"); $.ajax({ type:"post", url:"", async:true, data:formData, success:function (data) { }, error:function (e) { } }); });
三、结合layui踩的一些坑,以及最终的解决方法。
先看html部分:
<button type="button">上传图片</button> <div> </div> <input type="button" id = "btnHide">
就是这么简单。为什么要再写一个隐藏的按钮,之后解释。
js部分:
layui.use('upload', function() { var upload = layui.upload; var uploadInst = upload.render({ elem: '#upImg', url: '/upload/', auto: false, bindAction: "#btnHide", choose: function(obj) { var files = obj.pushFile(); var index, file, indexArr = []; for(index in files) { indexArr.push(index); }; var iaLen = indexArr.length; file = files[indexArr[iaLen - 1]]; for(var i = 0; i < iaLen - 1; i++) { delete files[indexArr[i]]; } try { if(file.size > 200 * 1024) { delete files[index]; photoCompress(file, { quality: 0.5, }, function(base64Codes) { var bl = convertBase64UrlToBlob(base64Codes); obj.resetFile(index, bl, file.name); $("#btnHide").trigger("click"); }); } else { $("#btnHide").trigger("click"); } } catch(e) { $("#btnHide").trigger("click"); } }, done: function(res) { //这里把后台返回的数据进行操作,展示上传完成的图片,具体数据格式参考layui的API }, error: function() { } }); });
原理:在选择照片之后,获取文件,转换为blob对象,使用resetFile方法对文件列队里的文件进行重新设置,然后再触发上传事件。
踩的坑:
1、resetFile这个方法是layui 2.3.0 新增的,所以首先要确保layui的版本是最新的。