ElementUI图片上传前对尺寸进行验证的方法
一.ElementUI的upload组件用法
具体的属性可以查看官方文档,这里用到的是:before-upload="beforeAvatarUpload"
这个钩子函数,看名字就知道这是在图片上传前执行的方法,在此可以进行一些验证,官方给出了对图片类型以及大小的验证,接下来将实现对图片尺寸的验证.
<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
参数打印出来看一下
可以看到里面包含了文件名称,大小,类型,但是没有图片的宽高.
要实现对图片宽高的验证,我这里是借助了javascript原生API FileReader
二.javascript原生API FileReader
先来学习一下这个api
的使用方法,然后再结合elementUI
进行验证
1、FileReader接口的方法
FileReader
接口有4个方法,其中3个用来读取文件,另一个用来中断读取。
- readAsText:该方法有两个参数,其中第二个参数是文本的编码方式,默认值为
UTF-8
。这个方法非常容易理解,将文件以文本方式读取,读取的结果即是这个文本文件中的内容。 - readAsBinaryString:该方法将文件读取为二进制字符串,通常我们将它传送到后端,后端可以通过这段字符串存储文件。
- readAsDataURL:这个方法将文件读取为一段以
data:
开头的字符串,这段字符串的实质就是Data URL
,Data URL
是一种将小文件直接嵌入文档的方案。我这里就使用这个方法.
2、FileReader接口事件
FileReader
接口包含了一套完整的事件模型,用于捕获读取文件时的状态。
3、FileReader 属性
无论读取成功或失败,方法并不会返回读取结果,这一结果存储在result
属性中。
4、FileReader 使用
FileReader
接口的使用方式非常简单,在不考虑浏览器兼容的情况下直接创建实例就可以了
let reader = new FileReader();
如果考虑浏览器,可以先检查一下
代码语言:javascript复制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
来获取宽高了,最后再进行验证就好了
看一下控制台打印结果,编码太长了,主要看一下红色框里的部分.看来获取到宽高是没问题的了
最后我们进行验证,由于FileReader
接口的onload
方法是异步方法,所以我们是拿不到img
属性的,为此我们借助Promise
最后的验证代码如下
代码语言:javascript复制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;
}
})
}
先用一个不符合要求的图片,
换一个符合要求的图片
大功告成,这样就可以在上传图片前进行尺寸验证啦!
验证通过以后自然就是要上传了
基于express图片上传到新浪云
目标功能:图片上传
操作流程:点击上传按钮->把图片上传到服务器->返回图片URL
1.组件中使用elementUI的上传
代码语言:javascript复制<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.上传图片到新浪云
偶然间发现新浪云可以上传图片用,数据量在一定范围内还是免费的,减少了自己本来就不富裕的服务器内存压力.
代码语言:javascript复制/*
* @Description: 图片上传接口
* @Author: hanzhiwei
* @Date: 2020-10-07 00:46:47
* @LastEditTime: 2020-10-13 00:42:41
* @FilePath: blogserveroutebloguploadArticleImg.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);
}
});
}
大功告成,此时新浪云就有我们上传的图片啦!
打个广告
这是我一个开源的收藏网址的项目
项目地址