zoukankan      html  css  js  c++  java
  • 移动端图片压缩上传解决方案

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

      

  • 相关阅读:
    docker的应用部署
    docker容器的数据卷
    找到最终的安全状态 深搜
    park和unpark方法详解
    docker容器相关命令
    docker鏡像相關命令
    join方法底层实现
    Elasticsearch启动过程错误汇总
    MySQL 8.0.12 报错The table does not comply with the requirements by an external plugin. (errno 3098)
    docker login 密码查看和加密保存
  • 原文地址:https://www.cnblogs.com/lvhw/p/6854419.html
Copyright © 2011-2022 走看看