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

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

 <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})
            }
          })
        }
      },

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容