elementUI upload 對圖片的寬高做校驗

幾分幾兩發表於2018-09-11

前言

在我使用vue+elementUI開發過程中遇到一個問題:upload 對圖片的寬高做校驗

一開始我直接百度google,發現都沒有這個問題,這應該是一個很常見的需求啊,element 為啥沒有實現呢,也許是很簡單吧,網上竟然沒有此類問題,我到GitHub的issue裡看,確實有類似的問題,但沒有系統的解決方法,涼涼。

既然沒有找到那就只能自己鼓搗了

思路

想要做圖片的寬高校驗那就要先獲取到圖片寬高資訊:image.onload

onload 事件在圖片載入完成後立即執行。

let image = new Image();
image.onload = function() {
    let width = image.width;
    let height = image.height;
};
image.src = "images/bg.jpg";
複製程式碼

獲取到資訊後那就可以進行比較了 比如我需要一張750*420尺寸的圖片

let width = 750;  //圖片寬度
let height = 420; //圖片高度
let image = new Image();
image.onload = function() {
    let isSize = image.width == width && image.height == height;
    if (!isSize) {
        that.$message.error("上傳頭像圖片尺寸不符合,只能是750*420");
    }
};
image.src = "images/bg.jpg";
複製程式碼

現在我想獲取到上傳的圖片資訊

beforeAvatarUpload(file) {
    // 上傳圖片前處理函式
    let width = 750;  //圖片寬度
    let height = 420; //圖片高度
    let _URL = window.URL || window.webkitURL;
    let image = new Image();
    img.onload = function() {
        let isSize = image.width == width && image.height == height;
        if (!isSize) {
            that.$message.error("上傳頭像圖片尺寸不符合,只能是750*420");
        }
        return isSize;
    };
    img.src = _URL.createObjectURL(file);
}
複製程式碼

現在isSize確實被重新賦值了,有了正確的提示,但只是一閃而過,併成功的上傳了,很鬱悶,一步步的開始debugger了,發現最後還是可以回到return的,但是不知道啥原因,接著又開始google了,發現我的思路是錯的。

仔細看了下掘金上的這篇文章JS 應用場景(Promise => 圖片上傳),發現upload人家內部確實是想要一個promise,你直接給isSize一個boolean值,最後return出去其實是沒有任何作用的,這就解釋了為何可以彈出錯誤資訊卻可以成功上傳了,這個是剛才的實現方法。

還是去看下原始碼吧,一看才有點兒眉目

upload(rawFile) {
    this.$refs.input.value = null;
    if (!this.beforeUpload) {
    return this.post(rawFile);
    }
    const before = this.beforeUpload(rawFile);
    if (before && before.then) {
    before.then(processedFile => {
        const fileType = Object.prototype.toString.call(processedFile);
        if (fileType === '[object File]' || fileType === '[object Blob]') {
        if (fileType === '[object Blob]') {
            processedFile = new File([processedFile], rawFile.name, {
            type: rawFile.type
            });
        }
        for (const p in rawFile) {
            if (rawFile.hasOwnProperty(p)) {
            processedFile[p] = rawFile[p];
            }
        }
        this.post(processedFile);
        } else {
        this.post(rawFile);
        }
    }, () => {
        this.onRemove(null, rawFile);
    });
    } else if (before !== false) {
         this.post(rawFile);
    } else {
         this.onRemove(null, rawFile);
    }
},
複製程式碼

這才發現this.beforeUpload是一個真正的promise,你給人家必須返回一個promise,簡單的boolean值是沒用的,因為人家內部還有很多的對promise的實現,這下清楚了一點,就順水推舟的有了最終的方法,經過多樣測試,的確可以。

最終版程式碼

beforeAvatarUpload(file) {
    // 上傳圖片前處理函式
    const isJPG =
        file.type === "image/jpeg" ||
        file.type === "image/png" ||
        file.type === "image/gif";
    const isLt2M = file.size / 1024 / 1024 < 2;
    let that = this;
    let isAllow = false;
    if (!isJPG) {
        this.$message.error("上傳頭像圖片只能是 jpg、png、gif 格式!");
    }
    if (!isLt2M) {
        this.$message.error("上傳頭像圖片大小不能超過 2MB!");
    }
    const isSize = new Promise(function(resolve, reject) {
        let width = 750;
        let height = 420;
        let _URL = window.URL || window.webkitURL;
        let image = new Image();
        image.onload = function() {
          let valid = image.width == width && image.height == height;
          valid ? resolve() : reject();
        };
        image.src = _URL.createObjectURL(file);
    }).then(
        () => {
          return file;
        },
        () => {
          this.$message.error("上傳頭像圖片尺寸不符合,只能是750*420!");
          return Promise.reject();
        }
      );
    return isJPG && isLt2M && isSize;
}
複製程式碼

看了最終版的程式碼發現確實也很簡單,我們往往被固有的思維帶入歧途,其實還是自己的功力不深啊,以後還是要多注重基礎,多挖掘細節,以小見大,修煉內功,共勉!

相關文章