ElementUI + express实现头像上传及后台图片保存

记录大创项目中的解决方式。只说明基本的实现方法,不代表实际代码。如果你需要在后台保存头像图片的话。

当然也可以直接使用base64格式保存头像,虽然有一些缺陷,这样后台就不需要保存图片了,直接保存base64的文本就行。

文章仅是自己个人在项目中的总结,如有不妥和遗漏还请多多指教。

1. 前端部分

先照搬elementUI的官方文档,再删删补补一下(样式部分暂且省略):

<!-- 设定的属性在官方文档里都有说明,就不再赘述 -->
<!-- 上传的地址:http://localhost/uploadAvatar  必须上传的文件字段名: avatar  可使用附带的数据:id(可用于验证),也可以不加用户在点击并选择好图片后会立即上传
-->
<el-uploadclass="avatar-uploader"action="http://localhost/uploadAvatar"name="avatar":data="{ id }":show-file-list="false":before-upload="beforeAvatarUpload":on-success="handleAvatarSuccess":on-error="handleAvatarError"><img v-if="imageUrl" :src="data:imageUrl" class="avatar" /><i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload><script>
export default {data() {return {imageUrl: "",id: '1234'}},methods: {//上传成功的方法handleAvatarSuccess(res) {if (res.err) return this.$message.error(res.msg);this.$message.success("头像上传成功!");},//上传失败的方法handleAvatarError() {this.$message.error("未知错误");},//上传之前的处理beforeAvatarUpload(file) {const isJPG = file.type === "image/jpeg" || file.type === "image/png";const isLt2M = file.size / 1024 / 1024 < 2;if (!isJPG) {this.$message.error("上传头像图片只能是 JPG 或者 PNG 格式!");}if (!isLt2M) {this.$message.error("上传头像图片大小不能超过 2MB!");}return isJPG && isLt2M;}}
}
</script>

2. 后台接口部分

需要使用images模块:

npm i images --save

该模块的文档地址:https://www.npmjs.com/package/images

我使用的是formdata格式传输的数据。

const express = require('express');
const images = require('images');const router = express.Router();   //二级路由router.use('/uploadAvatar', function (req, res) {//前端的参数使用req.fields获取,如果获取不到,请使用express-formidable模块并提取挂载const id = req.fields.id;    //先获取,实际情况有可能使用//这里提前定义一个图片保存的路径,为防止图片名有可能冲突,我做了一些处理const imgPath = `./img/avatars/${new Date().getTime() + Math.random().toFixed(3) * 1000}.jpg`;return new Promise((resolve, reject) => {try {//前端的文件使用req.files获取,因为前面的name属性,文件的字段名改成了avatar//根据文档保存图片:images(req.files.avatar.path)    .size(1920).save(imgPath, {quality: 80})resolve()}catch {reject()}}).then(() => {res.send({ err: 0, msg: '头像已上传'})}).catch(() => res.send({ err: 1, msg: '上传失败' }))
});module.exports = router;

到此为止,基本的前端头像上传和后端图片保存功能就实现了。再作一些补充。

补充:使用数据库保存用户的头像链接

如果是在自己的后台保存了用户上传的图片,同时你开启了静态资源服务,希望用户能直接访问服务器上的图片。

这时可能就需要在数据库的用户信息表中保存对应的头像链接。

//前面注释过的都删了,补充的部分作了注释const express = require('express');
const images = require('images');
const mysql = require('mysql');     //引入数据库模块const router = express.Router();router.use('/uploadAvatar', function (req, res) {const id = req.fields.id;    const imgPath = `./img/avatars/${new Date().getTime() + Math.random().toFixed(3) * 1000}.jpg`;return new Promise((resolve, reject) => {try {images(req.files.avatar.path)    .size(1920).save(imgPath, {quality: 80})resolve()}catch {reject()}}).then(() => {//对前面图片的保存路径作一些处理,加上前缀:const link = imgPath.replace('.', 'http://localhost');   //这样就产生了头像的http路径,我们可以直接根据该地址访问图片,如果你开启了静态资源服务的话//接下来就是常规的修改信息://将图片链接存入数据库const connection = mysql.createConnection({host: "localhost",user: "root",password: "",database: "test",});connection.connect(function (err) {err ? console.log("数据库链接失败") : console.log("链接成功!");});connection.query(`update user_info set profile='${link}' where id=${id}`,   //根据前端上传时附带的id找到对应用户(err, row) => {if (err) return res.send({ err: 1, msg: '上传失败' });res.send({ err: 0, msg: '头像已上传'})}}).catch(() => res.send({ err: 1, msg: '上传失败' }))
});module.exports = router;

补充:后台设置用户上传时限

设置用户多长时间能够上传一次头像。虽然前端也可以做,但后端更加保险。

同时因为后台是要保存头像图片,不排除一些用户可能恶意刷头像上传,如果没有及时清理会极大的占据并浪费硬盘空间。

当然我也并不知道正规公司是怎么做的,所以这可能有点多余。仅当作一个思路吧。

const timeLimt = {};  //一个全局对象变量router.use('/uploadAvatar', function (req, res) {const id = req.fields.id;    //1.接收用户id// 4.提前判断当前用户是否正在时限中,如果是则直接结束if (timeLimit[idCode]) return res.send({ err: 1, msg: '同一用户三分钟只能上传一次!' });const imgPath = `./img/avatars/${new Date().getTime() + Math.random().toFixed(3) * 1000}.jpg`;return new Promise((resolve, reject) => {try {images(req.files.avatar.path)    .size(1920).save(imgPath, {quality: 80})resolve()}catch { reject() }}).then(() => {res.send({ err: 0, msg: '头像已上传'})//2.每次上传成功,给全局变量添加一个当前用户id的属性并设置值:timeLimit[id] = true;  //代表当前用户正在时限中,无法更改//3. 三分钟后解除时限setTimeout(() => {timeLimit[id] = false;   }, 180000)}).catch(() => res.send({ err: 1, msg: '上传失败' }))
});module.exports = router;

写完之后再想想,似乎也可以在每次用户上传的时候,在数据库中查询对应用户的头像链接,更新之后再将原先保存的图片直接删除。
又或者按照设置时限的思路,每次用户上传就将头像路径和id绑定,再次上传时就先根据前一次绑定的头像路径将该图片删除,再绑定到对应id。
这样就保证服务器上每个用户只会保存一张头像图片,也就不存在多余的头像图片,也不用按时清理了。

不过不知道这样是否会对后台产生一些压力。所以暂且保存这个想法吧,毕竟也只是个小项目,我也只是个写前端的。

补充:确保一个用户只会保存一张头像

根据前面的想法,每次用户上传就将头像路径和id绑定,同一用户再次上传时就先根据前一次绑定的头像路径将该图片删除,再将新头像路径绑定到对应id。以此反复,保证服务器上每个用户只会保存一张头像图片。

//思路同设置时限
const id_avatarFile = {};  //一个全局对象变量router.use('/uploadAvatar', function (req, res) {const id = req.fields.id;   //2.异步删除前一次的图片if (id_avatarFile[idCode])  //如果存在的话fs.unlinkSync(id_avatarFile[idCode], (err) => {if (err) throw err;console.log('删除成功');})const imgPath = `./img/avatars/${new Date().getTime() + Math.random().toFixed(3) * 1000}.jpg`;return new Promise((resolve, reject) => {try {images(req.files.avatar.path)    .size(1920).save(imgPath, {quality: 80})resolve()}catch { reject() }}).then(() => {res.send({ err: 0, msg: '头像已上传'})//1. 保存第一次或前一次上传的头像链接id_avatarFile[idCode] = imgPath; }).catch(() => res.send({ err: 1, msg: '上传失败' }))
});module.exports = router;

实测可以成功,但是这样会出现一个新问题:每次用户重新打开界面时,首次上传时肯定是没有这条绑定的数据的,也就是为什么我需要先判断是否存在这样的数据才能执行删除文件的操作。这样每次一定会残余一张图片。

所以每次前端新上传图片时,第一次需要查询数据库并保存“id—路径”这样的数据,相当于初始化。之后直接执行上述的流程就可以了,也不用提前判断是否存在该条数据。

当然代码也很简单,就不再赘述了。

ElementUI + express实现头像上传及后台图片保存相关推荐

  1. element-ui的用户头像上传默认显示图片

    初始时为img获取一个图片

  2. android自定义头像上传,android裁切图片之用于头像上传

    嘛话都不说,直接贴代码,也是在网上找的代码copy出来的! 页面代码 encoding="utf-8"?> android:orientation="vertica ...

  3. Android头像上传时裁剪图片过大问题,裁剪大图片导致

    原先在完成头像上传功能的时候复制网上写好的代码,虽然也仔细研究过实现的过程但是这次项目中却遇到了一个很不解的问题,使用乐视手机实现图片裁剪的那一步骤中由于图片太大手机性能不够导致图片无法裁剪报出错误 ...

  4. java 跨域上传_java后台图片跨域上传图片 文件

    发送方 @ResponseBody @RequestMapping(value="/imgUpLoadNewOneKuaYu")public String imgUpLoadNew ...

  5. php 图片上载 wordpress,WordPress 使用 Jcorp上传并裁剪图片作为自定义头像 —— PHP 后台部分...

    在开发 WordPress 用户中心的时候,我们需要让用户在前段上传自定义图片作为头像,因为很多用户都是小白,上传头像之前要求他们按照尺寸裁剪好是不大现实的.为了提升用户体验,我研究测试了很久,终于搞 ...

  6. SpringBoot + Vue 头像上传案例

    头像上传 前言 后台系统一般会有用户个人信息的模块,为了增强用户的体验度,系统会开放自定义头像的功能,让用户可以上传自定义图片替代默认的系统头像.本文将通过SpringBoot+Vue来具体实现. 前 ...

  7. DISCUZ论坛插件h5手机电脑头像上传3.7.1带扩展插件【收集免费分享】

    一个支持电脑和手机h5技术头像上传的插件. 说明:本插件h5电脑版和h5手机版为自主全新开发的触屏版头像上传,体验好,性能好,绿色. 主要特点:支持H5电脑版和H5手机版头像上传. 支持鼠标和触屏操作 ...

  8. app头像上传vue_vue实现头像上传

    一.html部分: 二.js部分(由于本项目用ts写的,差异的地方请各位自己调整下) import {XtVue, Component, Watch, XtRouter,Prop} from &quo ...

  9. vue3头像上传组件

    用到了自定义组件v-model的双向绑定 使用input的type=file这个原生html元素,通过监听change事件,获取到选择的文件(注意,选择完文件值后,要把这个隐藏的input的type= ...

最新文章

  1. .NET开发辅助工具-ANTS Performance Profiler【转载】
  2. ubuntu分屏软件_ubuntu14.04终端分屏terminator的安装使用与配置
  3. 测量分类准确率的过程算坍缩吗?
  4. 【Docker】ADD COPY no such file or directory
  5. 【Pytorch神经网络基础理论篇】 05 矩阵计算
  6. Excel VBA利用事件对图表自动更新
  7. 线性求逆元模板_算法学习笔记(9):逆元
  8. 微信支付小年上线“点鞭炮,响优惠”活动 大额提现免费券限时发放
  9. jsp基础知识点——思维导图
  10. 无法完成验证,可能QQ文件已损坏,您需要重新安装QQ
  11. 如何自动生成PDF书签
  12. php 判断客户端类型,怎么使用php判断客户端的类型
  13. 设计模式(20):外观模式Facade
  14. 阿里云 echarts地图json生成器 精确到区县。
  15. Java8新特性之一:Lambda表达式
  16. 以流量为主导的发展方式,注定了直播带货无法逃脱电商的宿命
  17. 系统封装_Ghost光盘制作
  18. Java之socket网络编程
  19. 昭阳K4e-IIL 81Y2CTO1WW 键盘按键失灵 实际是主板故障
  20. nodejs服务使用pm2启动多个进程和进程守护,以及使用pm2-logrotate-ext分割日志

热门文章

  1. 动态规划之正则表达式匹配字符串
  2. Linux动态库的导出控制
  3. 第 190 场力扣周赛
  4. Nmap配合Masscan实现高效率扫描资产
  5. CentOS6.5 常用命令
  6. Linux系统编程:使用mutex互斥锁和条件变量实现多个生成者和消费者模型
  7. Python中MRO
  8. 如何解决comctl32.dll文件丢失的问题?
  9. 关于完全删除电脑上多余的tomcat服务器的解决办法
  10. redis持久化之rdb篇