移动端图片压缩上传解决方案

最近做移动端图片上传,发现图片尤其是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, {
           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;
      }
    },
  }

  

原文地址:https://www.cnblogs.com/lvhw/p/6854419.html