vue + Element 实现图片校验和压缩上传

870 阅读2分钟

图片压缩上传主要是将图片绘制到canvas上

一.创建element上传组件

<el-upload
  class="avatar-uploader-small"
  :action="xxxxx"
  :show-file-list="false"
  :before-upload="beforeAvatarUpload"
  >
  <img v-if="oneImg" :src="oneImg" class="avatar-small">
  <i v-else class="el-icon-plus avatar-uploader-small-icon"></i>
</el-upload>
/**
 * 图片校验入口
 */
beforeAvatarUpload (file) {
  // 可上传的图片类型
  let types = ['image/jpeg', 'image/jpg', 'image/png']
  return this.$img.imgRequir(file, types, 10)
},

二.编写 img.js 工具类

import ElementUI from 'element-ui';
/**
 * @Description: 校验图片大小和类型
 * @param file: 文件流
 * @param imgList: 图片类型
 * @param size: 最大大小
 * @Date 2020-07-08
*/
function imgRequir (file, imgList, size) {
  let isJPG = false;
  if (imgList.indexOf(file.type) !== -1) {
    isJPG = true
  }
  console.log(file, imgList, size, isJPG)
  const isLt2M = file.size / 1024 / 1024 < size;
  console.log("img-size:", file.size / 1024 / 1024)
  if (!isJPG) {
    ElementUI.Message({
      type: 'error',
      message: `图片格式只能为${[...imgList]}`
    })
    return false
  }
  if (!isLt2M) {
    ElementUI.Message({
      type: 'error',
      message: `上传头像图片大小不能超过 ${size}MB!`
    })
    return false
  }
  return new Promise(resolve => {
    console.log(file.size / 1024 / 1024 < 3);
    // 如果文件小于3Mb 则不进行压缩
    if (file.size / 1024 / 1024 < 3) {
      resolve(file)
    } else {
      const image = new Image()
      image.src = URL.createObjectURL(file)
      image.onload = function() {
        const that = this
        // 默认按比例压缩
        let w = that.width
        let h = that.height
        const scale = w / h
        w = file.width || w
        h = file.height || (w / scale)
        let quality = 0.7
        // 生成canvas
        const canvas = document.createElement('canvas')
        const ctx = canvas.getContext('2d')
        // 创建属性节点
        const anw = document.createAttribute('width')
        anw.nodeValue = w
        const anh = document.createAttribute('height')
        anh.nodeValue = h
        canvas.setAttributeNode(anw)
        canvas.setAttributeNode(anh)
        ctx.drawImage(that, 0, 0, w, h)
        // 图像质量
        if (file.quality && file.quality <= 1 && file.quality > 0) {
          quality = file.quality
        }
        // quality值越小,所绘制出的图像越模糊
        const data = canvas.toDataURL('image/jpeg', quality)
        // 压缩完成执行回调
        const newFile = convertBase64UrlToBlob(data)
        console.log(newFile.size / 1024 / 1024);
        resolve(newFile)
      }
    }
  });
}

/**
 * @Description: 转换base64格式
 * @param urlData : 图片rul
 * @Date 2020-07-13
*/
function convertBase64UrlToBlob(urlData) {
    const bytes = window.atob(urlData.split(',')[1]) // 去掉url的头,并转换为byte
    // 处理异常,将ascii码小于0的转换为大于0
    const ab = new ArrayBuffer(bytes.length)
    const ia = new Uint8Array(ab)
    for (let i = 0; i < bytes.length; i++) {
      ia[i] = bytes.charCodeAt(i)
    }
    return new Blob([ab], { type: 'image/png' })
  }

export default {
  imgRequir
}

3.运行结果