首页
归档
笔记
树洞
搜索
友言

文章详情

Interesting People Record Interesting.

/ JavaScript / 文章详情

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

Sonder
2023-02-16
6257字
16分钟
浏览 (1.7k)

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

复制代码
 <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, 如有侵权,请联系删除。

下一篇 / 还在用 JS 做节流吗?CSS 也可以防止按钮重复点击

🎯 相关文章

💡 推荐文章

🕵️‍♂️ 评论 (0)