img

vue 移动端input上传图片之处理图片

2023-02-16 0条评论 1.3k次阅读 JavaScript


前端开发中会有各种上传文件的需求,今天我们来说说上传图片
上传图片

 <input  type="file" @change="imageChange($event)"  accept="image/*"  multiple />

type:”file” 上传文件的格式
multiple :multiple 多张上传(不设置的话就是单张上传啦)
accept:image/* 上传类型(这里设置的是image/*,就是上传图片的所有类型啦,我们可以更加项目需求设置不同的类型 image/gif, image/jpeg)
点击input 选择图片触发@change="imageChange($event)"事件
选择后我们的到的是二进制流,
现在各大手机拍出的照片大小不一样,我们需要压缩图片,还要处理一部分手机照片上传后会有旋转的问题

// 上传图片
     imageChange(e){
     //e  选择图片后返回的所有参数  是数组的形式
       var imgs = e.target.files || e.dataTransfer.files;
       if (!imgs.length) return;
       let self = this
         for(var i=0;i<imgs.length;i++) {
           this.blobToBase64(imgs[i])  //转成 base64       
       }
     },

获取到的二进制文件 转 base64文件
这里需要引入插件 import EXIF from “exif-js”; ios上传照片会有旋转的问题

npm install exif-js -s
 /**
       * 获取到的二进制文件 转 base64文件
       * @param blob
       */
      blobToBase64 (blob) {
        const self = this // 绑定this
        const reader = new FileReader() //实例化一个reader文件
        reader.readAsDataURL(blob) // 添加二进制文件
        reader.onload = function (event) {
          const base64 = event.target.result // 获取到它的base64文件
          const scale = 0.3  // 设置缩放比例 (0-1)
          if(self.isiOS){  //判断是否是ios
//ios上传图片时会根据拍照时是横屏还是竖屏拍摄,图片会旋转的,我们要将图片旋转成正常
            EXIF.getData(blob, function() {
              EXIF.getAllTags(this);
              var  orientation = EXIF.getTag(this, 'Orientation');
              self.compressImg(base64,orientation, scale, self.gotoService) // 调用压缩方法
             //self.gotoService  压缩后上传至服务器
            });
          }else{
            self.compressImg(base64,0, scale, self.gotoService) // 调用压缩方法
          }
        }
      },

压缩图片方法

 /* 压缩图片方法
       * @param base64  ----baser64文件
         * @param scale ----压缩比例 画面质量0-9,数字越小文件越小画质越差
       * @param callback ---回调函数
       */
      compressImg (base64, orientation,scale, callback) {
        // 处理缩放,转换格式

        let self = this;
        const img = new Image() //new 一个图片
        img.src = base64
        img.onload = function () {
          const canvas = document.createElement('canvas') //    用canvas来压缩
          const ctx = canvas.getContext('2d')
          canvas.setAttribute('width', this.width)
          canvas.setAttribute('height', this.height)
          ctx.clearRect(0, 0, canvas.width, canvas.height)
          ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
          if(isIos){ //ios处理图片旋转
            if(orientation != "" && orientation != 1){
              switch(orientation){
                case 6://需要顺时针(向左)90度旋转
                  self.rotateImg(img,'left',canvas);
                  break;
                case 8://需要逆时针(向右)90度旋转
                  self.rotateImg(img,'right',canvas);
                  break;
                case 3://需要180度旋转
                  self.rotateImg(img,'right',canvas);//转两次
                  self.rotateImg(img,'right',canvas);
                  break;
              }
            }
          }
          // 转成base64 文件
          let base64 = canvas.toDataURL('image/jpeg')
          // 根据自己需求填写大小 我的目标是小于2兆
          while (base64.length > 1024 * 1024 * 2) {
            scale -= 0.01
            base64 = canvas.toDataURL('image/jpeg', scale)
          }
          // baser64 TO blob 这一块如果不懂可以自行百度,我就不加注释了
          const arr = base64.split(',')
          const mime = arr[0].match(/:(.*?);/)[1]
          const bytes = atob(arr[1])
          const bytesLength = bytes.length
          const u8arr = new Uint8Array(bytesLength)
          for (let i = 0; i < bytes.length; i++) {
            u8arr[i] = bytes.charCodeAt(i)
          }
          const blob = new Blob([u8arr], { type: mime })
          // 回调函数 根据需求返回二进制数据或者base64数据,我的项目都给返回了
          callback(blob, base64)
        }
      },

图片旋转

 //图片旋转
      rotateImg(img, direction, canvas) {
        //最小与最大旋转方向,图片旋转4次后回到原方向
        var min_step = 0;
        var max_step = 3;
        //var img = document.getElementById(pid);
        if (img == null)return;
        var height = canvas.height;
        var width = canvas.width;
        //var step = img.getAttribute('step');
        var step = 2;
        if (step == null) {
          step = min_step;
        }
        if (direction == 'right') {
          step++;
          //旋转到原位置,即超过最大值
          step > max_step && (step = min_step);
        } else {
          step--;
          step < min_step && (step = max_step);
        }
        //旋转角度以弧度值为参数
        var degree = step * 90 * Math.PI / 180;
        var ctx = canvas.getContext('2d');
        switch (step) {
          case 0:
            canvas.width = width;
            canvas.height = height;
            ctx.drawImage(img, 0, 0, width, height);
            break;
          case 1:
            canvas.width = height;
            canvas.height = width;
            ctx.rotate(degree);
            ctx.drawImage(img, 0, -height, width, height);
            break;
          case 2:
            canvas.width = width;
            canvas.height = height;
            ctx.rotate(degree);
            ctx.drawImage(img, -width, -height, width, height);
            break;
          case 3:
            canvas.width = height;
            canvas.height = width;
            ctx.rotate(degree);
            ctx.drawImage(img, -width, 0, width, height);
            break;
        }
      },

上传图片服务器

    //上传图片服务器
      gotoService(blob, base64){
        if (blob.size >= 2*1024*1024) {
          Toast('图片不得大于2M')
          return
        } else {
          var param = new FormData()
          param.append('file', blob, '.jpg')
          param.append('filename', blob + '.jpg')
          param.append('type', '1')
          let that = this
      //下面是用axios上传图片至服务器  根据自定义的项目api上传至服务器即可
          onUpload(param).then(res => {
            if (res.code == 200) {          
              that.images.push(res.data)
            } else {
              Toast({message:'上传失败'), duration: 2000})
            }
          })
        }
      },

到这里上传图片中的问题就都解决了,压缩图片,旋转图片 ,上传图片
如有不足,欢迎各位指导

本文转自 https://www.jianshu.com/p/294c7c3ad413, 如有侵权,请联系删除。

🏷️ #上传图片

💬 COMMENT


🦄 支持markdown语法

👋友