用的canvas。这个问题测试妹子反馈了好几回bug,解决了好屡次,虽然用了比较僵硬的办法,但总算最终解决了。javascript
由于php的同事说,页面上的图片要直接调用七牛的接口上传到七牛,因此后端那边不能处理,必须前端这边把图片处理到2m如下。但是我感受用以前的办法只是把宽高变小,并不能保证压缩后必定就小于2m。因此没办法吧,仍是得搞。php
/** * 将图片转化为base64 */ function imgBase64(file) { var self = this; // 看支持不支持FileReader if (!file || !window.FileReader) return; // 建立一个 Image 对象 var image = new Image(); // 绑定 load 事件处理器,加载完成后执行 image.onload = function(){ // 获取 canvas DOM 对象 var canvas = document.createElement('canvas') // 返回一个用于在画布上绘图的环境, '2d' 指定了您想要在画布上绘制的类型 var ctx = canvas.getContext('2d') // 若是高度超标 // 参数,最大高度 var MAX_HEIGHT = 9000; if(image.height > MAX_HEIGHT) { // 宽度等比例缩放 *= image.width *= MAX_HEIGHT / image.height; image.height = MAX_HEIGHT; } // 获取 canvas的 2d 环境对象, // 能够理解Context是管理员,canvas是房子 // canvas清屏 console.log('canvas.width:', canvas.width); ctx.clearRect(0, 0, canvas.width, canvas.height); // 重置canvas宽高 canvas.width = image.width; canvas.height = image.height; // 将图像绘制到canvas上 ctx.drawImage(image, 0, 0, image.width, image.height); // !!! 注意,image 没有加入到 dom之中 console.log(file.type); // console.log(canvas.toDataURL('image/jpeg',0.5)); //----------// var maxSize = 2*1024; // 2M var fileSize = file.size/1024; // 图片大小 if(fileSize > maxSize) { // 若是图片大小大于2m,进行压缩 console.log(maxSize,fileSize, maxSize/fileSize ); uploadSrc = canvas.toDataURL(file.type, maxSize/fileSize); document.getElementById('previewImage').src = uploadSrc; uploadFile = convertBase64UrlToFile(uploadSrc, file.name.split('.')[0]); // 转成file文件 } else { uploadSrc = canvas.toDataURL(file.type, 0.5); document.getElementById('previewImage').src = uploadSrc; uploadFile = file; } //--------// }; if (/^image/.test(file.type)) { // 建立一个reader var reader = new FileReader(); // 将图片将转成 base64 格式 reader.readAsDataURL(file); // 读取成功后的回调 reader.onload = function () { // 设置src属性,浏览器会自动加载。 // 记住必须先绑定事件,才能设置src属性,不然会出同步问题。 image.src = this.result; } } }
这段代码是找的以前别人写过的代码,而后本身加了点东西凑合用的。
以前没怎么弄过压缩图片,直觉以为不能把宽高压缩的过小,怕把图片给压缩模糊了,因而傻逼的把最大高度设置了9000。前端
var MAX_HEIGHT = 9000;
压缩的图片质量也设置了一个奇奇怪怪的值。java
uploadSrc = canvas.toDataURL(file.type, maxSize/fileSize);
测试了一波上线了,结果果真出问题了。测试同窗反馈用户的问题:压缩后会大于2m!因而脑子进水的改了一波。canvas
var maxSize = 1.5*1024; // 1.5M
结果又测出了问题:小于2m的图片压缩后会出现大于2m的状况!才突然想到一个问题,大于1.5m的图片转base64以后是可能大于2m的,本身就是瞎改。后端
因而又想着把最大高度改了,试试。顺便把图片质量下降。浏览器
var MAX_HEIGHT = 4000; ... uploadSrc = canvas.toDataURL(file.type, 0.3); // 把0.5改为了0.3
结果测试妹子测完后心虚的问,彻底没问题了么?内心也比较虚的不得了,干脆加了一个判断,压缩后仍是大于2m的话,就提示从新上传图片。当时都上线了,结果过了几天测试妹子一琢磨,这么提示仍是不友好,不合理,又开始敦促优化。dom
给改了方案,压缩以后若是大于2m,就再进行压缩,心想着这应该万无一失了,果真好久测试和用户都没再反映,至少经过了一段比较长时间的实践检验。
其实把最大高度还改小了一点,改为了3000,但感受也并什么用。测试
/** * 校验图片转换后大小并上传 */ function checkAndHandleUpload(file) { imgBase64(file, function (image, canvas) { var maxSize = 2*1024; // 2M var fileSize = file.size/1024; // 图片大小 if(fileSize > maxSize) { // 若是图片大小大于2m,进行压缩 console.log(maxSize,fileSize, maxSize/fileSize ); uploadSrc = canvas.toDataURL(file.type, maxSize/fileSize); uploadFile = convertBase64UrlToFile(uploadSrc, file.name.split('.')[0]); // 转成file文件 } else { uploadSrc = image.src; //canvas.toDataURL(file.type,0.5); uploadFile = file; } var compressedSize = uploadFile.size / 1024 / 1024; if(compressedSize.toFixed(2) > 2.00) { checkAndHandleUpload(uploadFile); } else { document.getElementById('previewImage').src = uploadSrc; } }); } /** * 将图片转化为base64 */ function imgBase64(file, callback) { var self = this; // 看支持不支持FileReader if (!file || !window.FileReader) return; // 建立一个 Image 对象 var image = new Image(); // 绑定 load 事件处理器,加载完成后执行 image.onload = function(){ // 获取 canvas DOM 对象 var canvas = document.createElement('canvas') // 返回一个用于在画布上绘图的环境, '2d' 指定了您想要在画布上绘制的类型 var ctx = canvas.getContext('2d') // 若是高度超标 // 参数,最大高度 var MAX_HEIGHT = 3000; if(image.height > MAX_HEIGHT) { // 宽度等比例缩放 *= image.width *= MAX_HEIGHT / image.height; image.height = MAX_HEIGHT; } // 获取 canvas的 2d 环境对象, // 能够理解Context是管理员,canvas是房子 // canvas清屏 console.log('canvas.width:', canvas.width); ctx.clearRect(0, 0, canvas.width, canvas.height); // 重置canvas宽高 canvas.width = image.width; canvas.height = image.height; // 将图像绘制到canvas上 ctx.drawImage(image, 0, 0, image.width, image.height); // !!! 注意,image 没有加入到 dom之中 console.log(file.type); // console.log(canvas.toDataURL('image/jpeg',0.5)); //----------// callback(image, canvas); //--------// }; if (/^image/.test(file.type)) { // 建立一个reader var reader = new FileReader(); // 将图片将转成 base64 格式 reader.readAsDataURL(file); // 读取成功后的回调 reader.onload = function () { // self.imgUrls.push(this.result); // 设置src属性,浏览器会自动加载。 // 记住必须先绑定事件,才能设置src属性,不然会出同步问题。 image.src = this.result; } } }