【解决方案】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

相关文章
相关标签/搜索