首页 > 技术文章 > vue + element 上传图片时压缩图片

lys597 2022-02-12 17:50 原文

方式一: 自动上传

html结构部分

 1  <el-upload
 2  class="avatar-uploader"
 3  action="/vab-mock-server/cloud/manager/common/aliyunStorage/upload"
 4  :on-success="handleMainSuccess"
 5  :before-upload="beforeAvatarUpload"
 6  :on-error="handleError"
 7  :show-file-list="false">
 9  <img
10    v-if="ruleForm.businessLicense"
11    :src="ruleForm.businessLicense"
12    class="avatar"/>
14  <i v-else class="el-icon-plus avatar-uploader-icon"></i>
15</el-upload>

 

 

 

 主要使用before-upload 钩子函数,涉及插件 image-Conversion

//插件安装
npm i image-conversion --save
//插件引入
import * as imageConversion from 'image-conversion';

javaScript部分

beforeAvatarUpload(file) {
     const isJpgOrPng = file.type === "image/jpeg" || file.type === "image/png";
     // 这里判断图片格式是否为jpeg或png 看实际情况使用
     if (!isJpgOrPng) {
       this.$message.error("上传图片只能是 JPG 或 PNG 格式!");
       return false;
     }
        const isLtM = file.size / 1024 / 1024 >= 1 // 这里对于大于 1M 的图片都进行压缩处理
     // 使用 Promise()防止没处理文件就上传 return new Promise((resolve) => { // 小于1M 不压缩 if (!isLtM) { resolve(file) } // 压缩到400KB,这里的400就是要压缩的大小,可自定义 imageConversion.compressAccurately(file, 400).then((res) => { resolve(res) }) //compressAccurately有多个参数时传入对象 //imageConversion.compressAccurately(file, { // size: 1024, //图片大小压缩到1024kb // width:1280 //宽度压缩到1280 //}).then(res => { //resolve(res) //}) }) },

方式二  手动上传

接口要以file类型随表单一起提交,这时就不能自动上传了,那么 el-upload组件的auto-upload这个属性就为false.
auto-upload为false 会导致 before-upload失效。但可以用 on-change钩子函数代替

但是这个钩子函数 不能接受Promise回调,所以使用imageConversion异步返回一个resolve结果,没办法接收,所以这里用到另一个压缩图片的方法,使用canvas画布压缩,
下面的压缩函数,可以放到你的公用工具js里

/** 图片压缩,默认同比例压缩
 *  @param {Object} fileObj
 *  图片对象
 *  回调函数有一个参数,base64的字符串数据
 */
export function compress(fileObj, callback) {
    try {
      const image = new Image()
      image.src = URL.createObjectURL(fileObj)
      image.onload = function() {
        const that = this
        // 默认按比例压缩
        let w = that.width
        let h = that.height
        const scale = w / h
        w = fileObj.width || w
        h = fileObj.height || (w / scale)
        let quality = 0.7 // 默认图片质量为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 (fileObj.quality && fileObj.quality <= 1 && fileObj.quality > 0) {
          quality = fileObj.quality
        }
        // quality值越小,所绘制出的图像越模糊
        const data = canvas.toDataURL('image/jpeg', quality)
        // 压缩完成执行回调
        const newFile = convertBase64UrlToBlob(data)
        callback(newFile)
      }
    } catch (e) {
      console.log('压缩失败!')
    }
  }
  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' })
  }

HTML部分

                <el-upload
                  class="upload-demo"
                  ref="uploadPrice"
                  action="#"
                  :auto-upload="false"
                  :on-change="fileChange"
                  :on-success="priceSuc"
                  :show-file-list="false"
                  :limit="5"
                  multiple
                >
                  <el-button slot="trigger" size="mini" type="primary"
                    >添加附件</el-button
                  >
                </el-upload>

JavaScript部分

    fileChange(file, fileList) {
      this.$refs.uploadPrice.clearFiles();
      let _this = this;
      let obj = {
        imgUrl: "",
        name: "",
      };
      let fileListData = [];
      for (let x = 0; x < fileList.length; x++) {
        let item1 = fileList[x];
        this.GLOBAL.compress(item1.raw, function (val) {
          let newfile = new window.File([val], file.name, { type: file.type });
          newfile.uid = file.uid;
          fileListData.push(newfile);
        });
        var file = item1.raw;
        obj.name = item1.name;
        var reader = new FileReader();
        reader.onload = function (e) {
          //转base64
          obj.imgUrl = e.target.result;
            _this.fileArr.push(obj); 
        };
        reader.readAsDataURL(file);
      }
      this.$set(this.form, "fileList", fileListData);
      // console.log(this.form.fileList);
    },

 

推荐阅读