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

本文介绍在Vue项目中使用vant组件库实现图片压缩上传的方法,通过前端压缩减轻服务器压力,提高上传效率。文章详细展示了如何利用Canvas对大尺寸图片进行压缩,并将其转换为base64编码,以便于网络传输。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前写过一篇关于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高,具体的宽高根据比例来更好。也没有用到所谓的压缩,本质就是将大图缩小然后上传。

转载于:https://juejin.im/post/5c1890b1518825046c2f67b7

Vue前端开发中,可以使用Vant组件库中的Uploader组件来实现图片上传功能。同时,为了减小上传文件的大小,可以使用JavaScript中的canvas API对图片进行压缩处理。具体步骤如下: 1. 在Vue项目中引入Vant组件库和exif-js库。 2. 在Uploader组件中设置上传图片的最大尺寸和格式。 3. 在上传前,使用exif-js库获取图片的方向参数,根据方向参数对图片进行旋转。 4. 使用canvas API对图片进行压缩处理,压缩后的图片上传至服务器。 代码示例: ``` <template> <van-uploader :max-size="2 * 1024 * 1024" :accept="['jpg', 'jpeg', 'png']" :before-upload="beforeUpload" :on-success="onSuccess" /> </template> <script> import EXIF from 'exif-js'; import { Toast } from 'vant'; export default { methods: { beforeUpload(file) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = (event) => { const img = new Image(); img.src = event.target.result; img.onload = () => { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); let width = img.width; let height = img.height; let orientation = 1; EXIF.getData(file, function() { orientation = EXIF.getTag(this, 'Orientation'); }); if ([5, 6, 7, 8].indexOf(orientation) > -1) { canvas.width = height; canvas.height = width; } else { canvas.width = width; canvas.height = height; } switch (orientation) { case 2: ctx.transform(-1, 0, 0, 1, width, 0); break; case 3: ctx.transform(-1, 0, 0, -1, width, height); break; case 4: ctx.transform(1, 0, 0, -1, 0, height); break; case 5: ctx.transform(0, 1, 1, 0, 0, 0); break; case 6: ctx.transform(0, 1, -1, 0, height, 0); break; case 7: ctx.transform(0, -1, -1, 0, height, width); break; case 8: ctx.transform(0, -1, 1, 0, 0, width); break; default: break; } ctx.drawImage(img, 0, 0, width, height); const base64 = canvas.toDataURL('image/jpeg', 0.8); const blob = this.dataURLtoBlob(base64); resolve(blob); }; }; }); }, onSuccess(response) { Toast.success('上传成功'); }, dataURLtoBlob(dataURL) { const arr = dataURL.split(','); const mime = arr[0].match(/:(.*?);/)[1]; const bstr = atob(arr[1]); let n = bstr.length; const u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new Blob([u8arr], { type: mime }); }, }, }; </script> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值