天天看點

Ant-Design-Vue 圖檔上傳

功能示範

我們要實作的功能如下,有兩個按鈕,點選第一個按鈕選擇檔案,選擇檔案後點選第二個按鈕上傳到伺服器。

功能需求:

  1. 隻允許上傳

    png

    jpg/jpeg

    格式的圖檔
  2. 沒有上傳圖檔時顯示占位圖
  3. 選擇完圖檔後在頁面中渲染出來
Ant-Design-Vue 圖檔上傳
Ant-Design-Vue 圖檔上傳
Ant-Design-Vue 圖檔上傳
Ant-Design-Vue 圖檔上傳

建構頁面

template

<template>
  <div>
    <div>
      <!-- 選擇圖檔後展示待上傳的圖檔 -->
      <img v-if="base64img" :src="base64img" />
      <!-- ↓ 沒有選擇時顯示占位圖 -->
      <img v-else="base64img" src="@/assets/placeholderImg.png" />
    </div>

    <!-- 限制最大待上傳的檔案數量為 1 -->
    <!-- 添加選擇檔案後的回調和移除待上傳檔案的回調 -->
    <a-upload :before-upload="beforeUpload" :max-count="1" @remove="handleRemove">
      <a-button>
        <upload-outlined></upload-outlined>
        Select File
      </a-button>
    </a-upload>
    <!-- 點選上傳按鈕 -->
    <a-button @click="triggerUpload" :loading="btnLoading">上傳</a-button>
  </div>
           

邏輯部分

import { UploadOutlined } from '@ant-design/icons-vue'
import fruitApi from "@/api/fruitApi";
import {ref} from "vue";
import {Upload} from "ant-design-vue";
import {Notice} from "@/utils/interfaces";

const fileList = ref();
// ↑ 待上傳檔案清單 (其實裡面也就能放一個檔案)
const base64img = ref();
// ↑ 我們在頁面中顯示待上傳的圖檔的原理是
// 将所選擇的本地圖檔轉換為 Base64 編碼
// 之後讓圖檔的 src = base64img 來實作的
// 是以 base64img 就是一個儲存圖檔編碼的字元串
const btnLoading = ref<boolean>(false);
// ↑ 上傳按鈕的 loading 狀态
// 在點選上傳 至 擷取伺服器回調的時間内 按鈕不可用

/**
 * 對圖檔編碼的函數
 */
function getBase64(img: Blob, callback: (base64Url: string) => void) {
  const reader = new FileReader();
  reader.addEventListener('load', () => callback(<string>reader.result));
  // ↑ 監聽 reader 的 load 事件,觸發時執行回調函數
  // 回調函數的作用就是将圖檔編碼的base64字元串傳給 base64img
  reader.readAsDataURL(img);
}

/**
 * andv 上傳檔案的回調
 * 傳回 false 則不會上傳檔案,而是由我們手動上傳
 * 傳回 Upload.LIST_IGNORE 會取消将檔案添加至待上傳清單
 * @param file 所選擇的檔案
 */
function beforeUpload(file: any) {
  console.log(file);
  // 判斷檔案是否為圖檔格式
  const isImg = (file.type === 'image/jpeg' || file.type === 'image/png');

  // 如果檔案不是圖檔格式則禁止上傳
  if (!isImg) {
    Notice.error("隻能上傳 jpeg/jpg/png 格式的檔案!");
    // ↑ Notice.error 是我自己寫的 Notice 類的一個靜态函數
    // 用的是 antdv 的 Notifiacation
    return Upload.LIST_IGNORE;
  }
  fileList.value = file;
  // ↓ 擷取所需要上傳圖檔的 Base64 編碼
  getBase64(fileList.value, (cb_img: string) => {
    // 将擷取到的所要上傳圖檔的 Base64 編碼渲染到圖檔上
    base64img.value = cb_img;
  })
  return false;
}

/**
 * 點選上傳按鈕的回調
 */
function triggerUpload() {
  const formData = new FormData();

  // 對檔案清單 判空
  if (fileList.value != null) {
    formData.append("file", fileList.value as any);
  } else {
    Notice.error("檔案不能為空!")
    return Upload.LIST_IGNORE;
  }

  // ↓ 在上傳過程中,按鈕為 loading 狀态
  btnLoading.value = true;

  // 請求上傳接口
  fruitApi({
    method: 'put',
    url: 'api/upload',
    data: formData
  })
      .then((resp: any) => {
        console.log(resp);
        if (resp.code === 1) {
          Notice.success(<string>resp.data);
          changeUploadItemColor("#49aa19");
        } else {
          Notice.error("上傳失敗~");
          changeUploadItemColor("#ff4d4f");
          // ↑ 下面會提到這個函數
        }
        btnLoading.value = false;
      })
      .catch((err) => {
        console.log(err);
        Notice.error("發生了錯誤~");
        btnLoading.value = false;
        changeUploadItemColor("#ff4d4f");
      })
}

/**
 * 待上傳圖檔被删除的回調
 */
function handleRemove() {
  fileList.value = null;
  // ↑ 置空待上傳檔案清單
  base64img.value = null;
  // ↑ 顯示預設占位圖
}


/**
 * 上傳圖檔成功或失敗後 list 變色的函數
 */
type uploadItemColor = "#49aa19" | "#ff4d4f";
// ↑ 兩個顔色 綠 和 紅
function changeUploadItemColor(color: uploadItemColor) {
  const uploadListItem = document.querySelector(".ant-upload-list-item-name");
  // ↑ 類名是 antdv 規定的,選擇這個類名即可
  (uploadListItem as any).style.color = color;
  // ↑ 使item文字變色
}
           

End

繼續閱讀