移动端图片压缩上传解决方案
最近做移动端图片上传,发现图片尤其是iPhone拍照的图片都有2M左右,但是实际上项目中用不到这么大,于是想到要用js在前台进行压缩。
解决方案如下:
网上搜了很多效果都不怎么好,这个还行:http://think2011.net/localResizeIMG/test/
使用可以参考具体文档,我是在Vue环境下,不过不影响使用,直接贴代码了:
import cropper from 'cropper' import imgUrl from '../assets/images/preview.png' import api from '../fetch/api' import VHeader from '@/components/Header.vue' import {Toast} from 'mint-ui' import {Indicator} from 'mint-ui' import lr from '../fetch/lrz.bundle' var data = {data: {}, appid: api.appid, id: ''}; var inputs = {}; export default { components: { VHeader }, data() { return { id: '', name: '', coverPic: '', iptList: {}, input: false, image: false, isEmpty: true, requireList: null, data: {data: {}, appid: api.appid, id: ''}, inputs: {}, imgSrc: '', cropImg: imgUrl, crop: '', cropper: false, ratio: '', shape: '', croppedCanvas: '', base64: '', picBlob: '', isPureFile: true, fileKey: '' } }, mounted() { this.getData(); this.requireList = document.getElementsByClassName('required'); document.getElementById('coverPic').onload = function () { if (document.body.scrollHeight - document.body.clientHeight > 20) { document.body.scrollTop = document.body.scrollHeight; } } }, methods: { getData() { let self = this; let id = self.$route.params.id; self.id = id; self.$http.get(api.getColumns + '1&id=' + id + api.defaultAppid) .then(res => { let result = res.data.data.result[0]; self.name = result.name; self.coverPic = result.previewPic || result.coverPic; self.iptList = result.inputs; self.ratio = result.inputs.picRatio || 1; }) .catch(function (error) { console.log('error' + error); }); }, getObjectURL(file) { var url = null; if (window.createObjectURL != undefined) { // basic url = window.createObjectURL(file); } else if (window.URL != undefined) { // mozilla(firefox) url = window.URL.createObjectURL(file); } else if (window.webkitURL != undefined) { // webkit or chrome url = window.webkitURL.createObjectURL(file); } return url; }, setImage(e) { let self = this; let objUrl; const file = e.target.files[0]; if (!file.type.includes('image/')) { Toast('请选择图片'); return; } if (file.size > 1024 * 1024 * 3) { Toast('图片不能大于3M'); return; } else if (file.size > 1024 * 1024 * 1) {//大于1M就进行压缩 self.compress(file) } else { var reader = new FileReader(); reader.readAsDataURL(file); reader.onload = function (e) { var objUrl = e.target.result; //self.picBlob = self.getBlob(objUrl); $('.cropper').append('<img id="uploadImg" src="" class="uploadImgC">'); $('#uploadImg').attr('src', objUrl); $('#uploadImg').cropper({ aspectRatio: self.ratio, //裁剪比例 viewMode: 1, }); } } this.cropper = true; }, sure() { let self = this; self.croppedCanvas = $('#uploadImg').cropper('getCroppedCanvas'); if (self.shape == '0') { // Round self.croppedCanvas = this.getRoundedCanvas(self.croppedCanvas); } let objUrl = self.croppedCanvas.toDataURL(); self.base64 = objUrl; self.picBlob = self.getBlob(objUrl); console.log('blob' + self.picBlob.size / 1024 / 1024); $('#priviewImg').attr('src', objUrl); $('#uploadImg').cropper('clear'); $('#uploadImg').remove(); $('.cropper-container').remove(); self.cropper = false; }, rotate() { $('#uploadImg').cropper('rotate', 20); }, compress(file){ let self=this; lrz(file, { width: 800 }) .then(function (rst) { // 处理成功会执行 // console.log(rst); // after.src = rst.base64; var objUrl = rst.base64; console.log('base64:' + objUrl.length/1024/1024+'M'); $('.cropper').append('<img id="uploadImg" src="" class="uploadImgC">'); $('#uploadImg').attr('src', objUrl); $('#uploadImg').cropper({ aspectRatio: self.ratio, //裁剪比例 viewMode: 1, }); }) .catch(function (err) { }) .always(function () { }); }, makePic() { let self = this; let list = [].slice.call(this.requireList), len = list.length, i = 0; for (i in list) { let input = list[i]; if (input.type == 'file') { if (input.value == '') { Toast('请先上传图片'); this.isEmpty = false; return false; } else { this.isEmpty = true; } } else if (input.type == 'text') { self.isPureFile = false; let len = input.value.replace(/[ ]/g, "").length; let v = input.attributes['maxlength'].nodeValue; let n; if (v == 0) { n = 4; } if (len < 1 || len > Number(v)) { n = v; Toast({ message: (`请输入1-${n}个字符`), duration: 400 }); this.isEmpty = false; return false; } else { this.isEmpty = true; } } else { this.isEmpty = true; } } if (this.isEmpty == true) { let list = [].slice.call(this.requireList), len = list.length, i = 0; for (i in list) { let input = list[i]; var iptsName = input.getAttribute('iptkey'); if (input.type == 'file') { // console.log(this.base64.length); // console.log(this.getBlob(this.base64).size); // this.inputs[iptsName] = this.base64; self.fileKey = iptsName; } else { let v = input.value; let em = v.replace(/[ ]/g, ""); if (/^\d+(\.\d+)?$/.test(em)) { v = em } this.inputs[iptsName] = v; } } // this.data.id = this.id; // this.data.data = JSON.stringify(this.inputs); var formData = new FormData(); // let key = document.querySelectorAll('input[type=file]')[0].getAttribute('iptkey') + ''; formData.append(self.fileKey, self.picBlob); if (!self.isPureFile) { formData.append('data', JSON.stringify(self.inputs)); } formData.append('id', self.id); formData.append('appid', api.appid); $.ajax({ url: api.baseUrl + '/pic/composite', type: 'post', data: formData, processData: false, contentType: false, beforeSend: function () { Indicator.open({ text: '制作中...', spinnerType: 'snake' }); console.log(self.picBlob.size / 1024 / 1024); }, success: function (data) { Indicator.close(); self.$router.push({name: 'result', params: {param: JSON.stringify(data)}}) } }) } }, getRoundedCanvas (sourceCanvas) { var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); var width = sourceCanvas.width; var height = sourceCanvas.height; canvas.width = width; canvas.height = height; context.imageSmoothingEnabled = true; context.drawImage(sourceCanvas, 0, 0, width, height); context.globalCompositeOperation = 'destination-in'; context.beginPath(); context.arc(width / 2, height / 2, Math.min(width, height) / 2, 0, 2 * Math.PI, true); context.fill(); return canvas; }, getBlob(dataURI){ var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; // mime类型 var byteString = atob(dataURI.split(',')[1]); //base64 解码 var arrayBuffer = new ArrayBuffer(byteString.length); //创建缓冲数组 var intArray = new Uint8Array(arrayBuffer); //创建视图 for (var i = 0; i < byteString.length; i += 1) { intArray[i] = byteString.charCodeAt(i); } var blob = new Blob([intArray], {type: mimeString}); //转成blob return blob; } }, }