【解決方案】ElementUI圖片上傳前如何對尺寸進行驗證而且上傳到新浪SCS?

ElementUI圖片上傳前對尺寸進行驗證的方法

一.ElementUI的upload組件用法

具體的屬性能夠查看官方文檔,這裏用到的是:before-upload="beforeAvatarUpload" 這個鉤子函數,看名字就知道這是在圖片上傳前執行的方法,在此能夠進行一些驗證,官方給出了對圖片類型以及大小的驗證,接下來將實現對圖片尺寸的驗證.javascript

<template>
  <div class="blog-main-views"> <el-upload class="avatar-uploader" action="https://jsonplaceholder.typicode.com/posts/" :show-file-list="false" :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload"> <img v-if="imageUrl" :src="imageUrl" class="avatar"> <i v-else class="el-icon-plus avatar-uploader-icon"></i> </el-upload> </div> </template>
 methods: {
    beforeAvatarUpload(file) {
      const isJPG = file.type === 'image/jpeg';
      const isLt2M = file.size / 1024 / 1024 < 2;
      if (!isJPG) {
        this.$message.error('上傳頭像圖片只能是 JPG 格式!');
      }
      if (!isLt2M) {
        this.$message.error('上傳頭像圖片大小不能超過 2MB!');
      }
      return isJPG && isLt2M;
    }
  }
}
複製代碼

這裏咱們把file參數打印出來看一下html

image.png

能夠看到裏面包含了文件名稱,大小,類型,可是沒有圖片的寬高.前端

要實現對圖片寬高的驗證,我這裏是藉助了javascript原生API FileReaderjava

二.javascript原生API FileReader

先來學習一下這個api的使用方法,而後再結合elementUI進行驗證git

一、FileReader接口的方法

FileReader接口有4個方法,其中3個用來讀取文件,另外一個用來中斷讀取。github

微信截圖_20210608153953.png

  • readAsText:該方法有兩個參數,其中第二個參數是文本的編碼方式,默認值爲 UTF-8。這個方法很是容易理解,將文件以文本方式讀取,讀取的結果便是這個文本文件中的內容。express

  • readAsBinaryString:該方法將文件讀取爲二進制字符串,一般咱們將它傳送到後端,後端能夠經過這段字符串存儲文件。json

  • readAsDataURL:這個方法將文件讀取爲一段以data:開頭的字符串,這段字符串的實質就是 Data URLData URL是一種將小文件直接嵌入文檔的方案。我這裏就使用這個方法.後端

二、FileReader接口事件

FileReader接口包含了一套完整的事件模型,用於捕獲讀取文件時的狀態。api

微信截圖_20210608154142.png

三、FileReader 屬性

不管讀取成功或失敗,方法並不會返回讀取結果,這一結果存儲在result屬性中。

四、FileReader 使用

FileReader接口的使用方式很是簡單,在不考慮瀏覽器兼容的狀況下直接建立實例就能夠了

let reader = new FileReader();
複製代碼

若是考慮瀏覽器,能夠先檢查一下

if(window.FileReader) {
    let reader = new FileReader();
}
else {
    alert("瀏覽器不支持 換個吧!!");
}
複製代碼

三.ElementUI與FileReader的結合實現驗證

既然是獲取圖片的寬高,那麼我這裏也是藉助了圖片來進行驗證,既然是圖片,咱們就要用到FileReader接口的readAsDataURL方法,

beforeAvatarUpload(file) {
  let reader = new FileReader();
  reader.onload = function () {
    let txt = this.result;
    let img = document.createElement("img");
    img.src = txt;
    img.onload = function () {
      console.log(img.width);
      console.log(img.height);
    }
  };
  reader.readAsDataURL(file);
}
複製代碼

咱們經過readAsDataURL獲取到的結果,恰好能夠賦給img標籤做爲src屬性,而後咱們就能夠經過最簡單的img.width以及img.height來獲取寬高了,最後再進行驗證就行了

看一下控制檯打印結果,編碼太長了,主要看一下紅色框裏的部分.看來獲取到寬高是沒問題的了

111.png

最後咱們進行驗證,因爲FileReader接口的onload方法是異步方法,因此咱們是拿不到img屬性的,爲此咱們藉助Promise

最後的驗證代碼以下

beforeAvatarUpload(file) {
      let _this = this;
      return new Promise(resolve => {
        let reader = new FileReader()
        reader.readAsDataURL(file);
        reader.onload = function () {
          resolve(this.result)
        }
      }).then((result) => {
        document.querySelector("#img").src = result;
        let img = document.querySelector("#img")
        img.onload = function () {
          console.log(img.width)
          console.log(img.height)
          const isWidth = img.width < 500
          const isHeight = img.height < 500
          console.log(isWidth)
          console.log(isHeight)
          if (!isWidth) {
            _this.$message.error('上傳頭像圖片寬度不能超過500!');
          }
          if (!isHeight) {
            _this.$message.error('上傳頭像圖高度不能超過500!');
          }
          return isWidth && isHeight;
        }
      })
    }
複製代碼

先用一個不符合要求的圖片,

image (1).png

換一個符合要求的圖片

image (2).png

大功告成,這樣就能夠在上傳圖片前進行尺寸驗證啦!

驗證經過之後天然就是要上傳了

基於express圖片上傳到新浪雲

目標功能:圖片上傳

操做流程:點擊上傳按鈕->把圖片上傳到服務器->返回圖片URL

1.組件中使用elementUI的上傳

<el-upload
      class="avatar-uploader"
      action="http://81.xx.xx.113:3000/blog/uploadArticleImg"
      :show-file-list="false"
      :on-success="handleAvatarSuccess"
      :before-upload="beforeAvatarUpload"
    >
      <img v-if="imageUrl" :src="imageUrl" class="avatar" />
      <i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
複製代碼

action裏面寫上傳圖片的接口

2.配置靜態資源文件夾

只有配置了靜態資源文件夾纔可使用URL的方式訪問圖片,這裏開放靜態資源文件夾必定要在dist前面,否則的話就會走html從而訪問不到圖片

//開放靜態資源文件
app.use(express.static(path.join(__dirname, "public")));

// 訪問靜態資源文件 這裏是訪問全部dist目錄下的靜態資源文件
app.use(express.static(path.resolve(__dirname, './dist')));
// 由於是單頁應用 全部請求都走/dist/index.html
app.get('*', function(req, res) {
    const html = fs.readFileSync(path.resolve(__dirname, './dist/index.html'), 'utf-8');
    res.send(html);
})
複製代碼

3.上傳圖片接口

服務器端使用的是multer模塊來處理上傳的圖片,使用post方式,並添加upload.single('file')

//blog.js

//圖片上傳模塊
const multer = require('multer')
//配置上傳路徑
const upload = multer({ dest: __dirname + '../../public/uploads' })
//upload.single()表示單個文件的上傳 
blog.post('/uploadArticleImg', upload.single('file'), require("./blog/uploadArticleImg"));
複製代碼

可是這個multer模塊處理文件有個坑(更多是我不懂配置),就是它會把上傳的文件名更換成隨機亂碼,而且不會保留後綴,這就致使前端訪問的時候直接下載了這個文件,而不是展現圖片.爲此 ,須要用path模塊解析原文件後綴名,而後用fs的方法給文件添加後綴

//uploadArticleImg.js

//引入path模塊
const path = require("path");
//引入fs模塊
const fs = require("fs");
module.exports = async(req, res) => {
    //接收文件信息
    const file = req.file;
    //獲取原文件名的後綴
    const suffix = path.parse(req.file.originalname).ext;
    //舊的文件名
    const oldname = req.file.path;
    //新的文件名
    const newname = req.file.path + suffix;
    //調用fs.renameSync()方法添加後綴
    fs.renameSync(oldname, newname);
    //獲取圖片的URL
    file.url = `http://81.70.96.113:3000/uploads/${file.filename}` + suffix;
    //返回文件信息
    res.send(file);
}
複製代碼

到這裏就能夠正常上傳圖片,而且返回圖片的URL

4.上傳圖片到新浪雲

偶然間發現新浪雲能夠上傳圖片用,數據量在必定範圍內仍是免費的,減小了本身原本就不富裕的服務器內存壓力.

/* * @Description: 圖片上傳接口 * @Author: hanzhiwei * @Date: 2020-10-07 00:46:47 * @LastEditTime: 2020-10-13 00:42:41 * @FilePath: \blog\serve\route\blog\uploadArticleImg.js */
//引入path模塊
const path = require("path");
//引入fs模塊
const fs = require("fs");

//新浪sdk引用
const sinaCloud = require('scs-sdk');
//配置新浪雲的accessKey和secretKey 我理解的就是帳號密碼
const config = new sinaCloud.Config({
    accessKeyId: '2wesaabmtYD4N3SwxkfM',
    secretAccessKey: 'e75005531b2e364d72efb8ee729f0825629a158a',
    sslEnabled: false
});

//實例化新浪雲儲存
var myBucket = new sinaCloud.S3({ params: { Bucket: 'duwanyu.com' } });
//當前實例生效:
myBucket.config = config;


module.exports = async(req, res) => {
    //接收文件信息
    const file = req.file;
    //獲取原文件名的後綴
    const suffix = path.parse(req.file.originalname).ext;
    //舊的文件名(模塊生成的亂碼)
    const oldname = req.file.path;
    //新的文件名
    const newname = req.file.path + suffix;

    //調用fs.renameSync()方法添加後綴
    fs.renameSync(oldname, newname);
    //獲取圖片的URL
    // file.url = `http://81.70.96.113:3000/uploads/${file.filename}` + suffix;
    //原文件名(文件自己名字)
    const remoteFilename = req.file.originalname;
    //根據新文件名讀取文件
    const fileBuffer = fs.readFileSync(newname);

    //上傳文件
    myBucket.putObject({
        ACL: 'public-read', //權限
        Bucket: 'duwanyu.com/images', //上傳至duwanyu.com文件夾裏的images文件夾裏
        Key: remoteFilename, //上傳到新浪雲的文件名
        Body: fileBuffer //文件
    }, function(error, response) {
        if (error) {
            res.json("上傳新浪雲失敗");
        } else {
            //上傳圖片成功,將圖片地址返回給前端
            file.sinaPath = "http://sinacloud.net/duwanyu.com/images/" + remoteFilename;
            //獲取圖片的URL
            file.url = `http://81.70.96.113:3000/uploads/${file.filename}` + suffix;
            //返回文件信息
            res.send(file);

        }
    });
}
複製代碼

大功告成,此時新浪雲就有咱們上傳的圖片啦!

打個廣告

16.gif 這是我一個開源的收藏網址的項目

項目地址👉👉點擊進入,能夠直接設置爲瀏覽器主頁或者桌面快捷方式進行使用,本人在用,長期維護。

徹底開源,你們能夠隨意研究,二次開發。固然仍是十分歡迎你們點個Star⭐⭐⭐
👉👉源碼連接(gitee)       👉👉源碼連接(github)

連接整合

🔊項目預覽地址(GitHub Pages):👉👉alanhzw.github.io

🔊項目預覽備用地址(本身的服務器):👉👉warbler.duwanyu.com

🔊源碼地址(gitee):👉👉gitee.com/hzw_0174/wa…

🔊源碼地址(github):👉👉github.com/alanhzw/War…

🔊個人博客:👉👉www.duwanyu.com

相關文章
相關標籤/搜索