Vue使用vant上传组件上传图片并对大图压缩

10,377 阅读3分钟

之前写过一篇关于Golang后端如何对图片进行base64解码并保存至文件服务器的文章传送门,现在补充前端vue框架下如何对图片压缩上传(使用了vant的上传组件)。

选择前端压缩的原因

减轻服务端压力,减少流量。

Vue使用vant的上传组件

    <van-cell-group>
      <van-cell title="上传图片">
        <van-uploader :after-read="uploadImg" 
          accept="image/gif, image/jpeg ,image/png"
          :max-size=6000000
          @oversize="overSize" >          
          <van-icon name="photograph"/>
        </van-uploader>
      </van-cell>
    </van-cell-group>

    <div class="show-img">
      <div class="item" v-for="(item, index) in imgBase64" :key="index">
        <span class="cancel-btn" @click="delImg(index)">x</span>
        <img :src="item">
      </div>
    </div>
    
    //script中定义imgBase64图片数组,存放base64编码的图片
    data() {
      return {
        imgBase64: [],
      }
    },
  • 第一段是vant的上传组件,包含uploadImg和overSize方法。
  • 第二段用来在页面中展示添加的图片。包含图片数组imgBase64,和删除图片的方法delImg。

uploadImg方法是本文的重点

  uploadImg(file) {
    // 大于1.5MB的jpeg和png图片都缩小像素上传
    if(/\/(?:jpeg|png)/i.test(file.file.type)&&file.file.size>1500000) {
      // 创建Canvas对象(画布)
      let canvas =  document.createElement('canvas')  
      // 获取对应的CanvasRenderingContext2D对象(画笔)
      let context = canvas.getContext('2d') 
      // 创建新的图片对象 
      let img = new Image()
      // 指定图片的DataURL(图片的base64编码数据)
      img.src = file.content
      // 监听浏览器加载图片完成,然后进行绘制
      img.onload = () => {
        // 指定canvas画布大小,该大小为最后生成图片的大小
        canvas.width = 400
        canvas.height = 300
        /* drawImage画布绘制的方法。(0,0)表示以Canvas画布左上角为起点,400,300是将图片按给定的像素进行缩小。*/
        /* 如果不指定缩小的像素,图片将以图片原始大小进行绘制,图片像素如果大于画布将会从左上角开始按画布大小部分绘制图片,最后得到的图片就是张局部图。图片小于画布就会有黑边。*/ 
        context.drawImage(img, 0, 0, 400, 300)
        // 将绘制完成的图片重新转化为base64编码,file.file.type为图片类型,0.92为默认压缩质量
        file.content = canvas.toDataURL(file.file.type, 0.92) 
        // 最后将base64编码的图片保存到数组中,留待上传。
        if(this.imgBase64.length < 6) {
          this.imgBase64.push(file.content)
        }else{
          alert("最多上传6张图片")
        }
      }                       
    }else{
      // 不做处理的jpg和png以及gif直接保存到数组
      if(this.imgBase64.length < 6) {
        this.imgBase64.push(file.content)
      }else{
        alert("最多上传6张图片")
      }
    }
  },

当我们用vant的上传图片组件选中一张图片时,就会触发该方法,形参file中包含了content和file对象,content是组件为我们自动处理的base64编码图片,直接就能在网页中显示。图片处理代码中有详细的注释。

最后imgBase64数组收集了所有要上传图片的base64编码,进行上传

  //post请求
  post(url, data) {
    let storage = window.localStorage
    return new Promise((resolve) => {
      axios({
        method: 'post',
        url: url,
        data: JSON.stringify(data),//将post请求的数据转化为json对象
        headers: { 'Authorization': storage.token,'Content-Type': 'application/json; charset=UTF-8'},
        cancelToken: new CancelToken(c => {
          cancel = c
        })
      }).then(res => {
        resolve(res)
      })
    })
  },
  
  axios.post(
    '/v2/publish',
    {
      imgList: this.imgBase64
    }
  )
  .then( response => {
  )
  • 第一段代码是我对axios的post方法封装,使用json格式传输给后端。
  • 第二段代码是上传请求,给imgBase64数组取了键名imgList,后端根据键名imgList就能拿到图片数组,再进行base64解码就能得到图片然后保存至文件服务器了(在我的另一篇文章有讲)。

本文没有过多的讲解,只是提供一个处理的思路,另外图片的压缩我也只是简单缩小到400宽300高,具体的宽高根据比例来更好。也没有用到所谓的压缩,本质就是将大图缩小然后上传。