1. 程式人生 > 實用技巧 >Vue 圖片壓縮上傳: element-ui + lrz

Vue 圖片壓縮上傳: element-ui + lrz

步驟

  • 安裝依賴包 npm install --save lrz
  • main.js裡引入 import lrz from 'lrz'
  • 封裝 compress函式
  • 封裝上傳元件 upload-image
  • 在 vue 檔案中 使用

封裝 compress函式

// eslint-disable

/** @format */
// base64編碼轉File
export function dataURLtoFile(dataurl, filename) {
  var arr = dataurl.split(','),
    mime = arr[0].match(/:(.*?);/)[1],
    bstr = atob(arr[1]),
    n = bstr.length,
    u8arr = new Uint8Array(n);
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new File([u8arr], filename, { type: mime });
}

// main function.
export function compress(file, fileList, that, reference) {
  if (file.status != 'ready') {
    return;
  }
  let index = reference.uploadFiles.indexOf(file);

  // jpg/jpeg/bmp/gif/png
  let isJPG =
    file.raw.type === 'image/jpg' ||
    file.raw.type === 'image/jpeg' ||
    file.raw.type === 'image/png' ||
    file.raw.type === 'image/gif' ||
    file.raw.type === 'image/bmp'

  const isLt20M = file.size / 1024 / 1024 < 20;
  if (!isJPG) {
    that.$message.error('不支援的格式,請上傳jpg/jpeg/bmp/gif/png格式的圖片!');
    fileList.splice(fileList.indexOf(file), 1);
    return;
  }
  if (!isLt20M) {
    that.$message.error('上傳圖片大小不能超過 20MB!');
    fileList.splice(fileList.indexOf(file), 1);
    return;
  }
  if (isJPG & isLt20M) {
    if (isLt2M(file)) {
      // pdf不壓縮
      submit(reference, file);
    } else {
      let options = {};
      lrz(file.raw, options)
        .then(rst => {
          let tempFile = dataURLtoFile(rst.base64, rst.origin.name);
          tempFile.uid = rst.origin.uid;
          reference.uploadFiles[index].raw = tempFile;
          reference.uploadFiles[index].size = rst.fileLen;
        })
        .catch(function (error) {
          // 失敗時執行
          if (error) {
            // IE報錯
            if (error.name == 'TypeError' && error.message == '物件不支援此操作') {
              that.$message.error('當前瀏覽器不支援上傳大於2M的檔案,請更換瀏覽器!');
            }
            // 圖片格式問題
            else if ((error + '').indexOf('載入圖片檔案失敗') > -1) {
              that.$message.error('系統未能識別當前上傳圖片,請更換!');
            }
          }
          fileList.splice(fileList.indexOf(file), 1);
        })
        .always(function () {
          //不管成功或失敗都會執行
          submit(reference, file);
        });
    }
  }
}
// 判斷檔案大小是否小於2M
function isLt2M(file) {
  if (file.raw.type === 'application/pdf') {
    return true;
  } else {
    return file.size / 1024 / 1024 < 2;
  }
}

function submit(reference, file) {
  let submitFlag = true;
  if (reference.multiple) {
    for (let item of reference.uploadFiles) {
      if (item.status != 'ready') {
        continue;
      }
      if (!isLt2M(item)) {
        submitFlag = false;
        break;
      } else {
        submitFlag = true;
      }
    }
  } else {
    if (!isLt2M(file)) {
      submitFlag = false;
    } else {
      submitFlag = true;
    }
  }
  if (submitFlag) {
    reference.submit();
    return;
  }
}

封裝上傳元件upload-image

<template>
  <div class="upload-component-container">
    <div class="upload-section">
      <!-- 上傳主體 -->
      <el-row>
        <el-upload
          ref="imageUploadRef"
          :headers="token"
          :action="uploadUrl"
          :auto-upload="false"
          list-type="picture-card"
          :file-list="imageList"
          :on-change="resize"
          :on-remove="handleRemove"
          :on-preview="handlePreview"
          :on-success="handleSuccess"
          :on-error="handleError"
          :on-exceed="handleExceed"
          :on-progress="handleProgress"
          :class="imageList.length >= maxCount ? 'uploaded-none':''"
          :limit="maxCount"
        >
          <div class="icon-container" v-loading="loading">
            <i class="el-icon-plus upload-icon"></i>
          </div>
        </el-upload>
      </el-row>
      <!-- 上傳描述 -->
      <el-row v-if="needDesc">
        <div class="upload-text-desc" :style="descStyle">{{uploadDesc}}</div>
      </el-row>
    </div>
    <!--