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

7 篇文章 0 订阅
3 篇文章 0 订阅

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

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

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

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

1. 前端部分

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

<!-- 设定的属性在官方文档里都有说明,就不再赘述 --> 
<!-- 
     上传的地址:http://localhost/uploadAvatar  必须
     上传的文件字段名: avatar  可使用
     附带的数据:id(可用于验证),也可以不加
     用户在点击并选择好图片后会立即上传
-->
<el-upload
    class="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="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—路径”这样的数据,相当于初始化。之后直接执行上述的流程就可以了,也不用提前判断是否存在该条数据。

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

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用VueExpressexpress-fileupload、jsonserver和Element UI来实现图片上传,并将其存放到指定位置。下面是一个简单的步骤指南: 1. 在Vue项目中安装Element UI组件库: ```bash npm install element-ui ``` 2. 创建一个Vue组件,用于实现图片上传的功能。你可以使用Element UI的上传组件: ```javascript <template> <div> <el-upload class="upload-demo" action="/api/upload" :before-upload="beforeUpload" :on-success="onSuccess" :file-list="fileList" multiple > <el-button size="small" type="primary">点击上传</el-button> </el-upload> </div> </template> <script> export default { data() { return { fileList: [] }; }, methods: { beforeUpload(file) { // 在上传之前的操作,比如限制文件类型和大小 }, onSuccess(response, file, fileList) { // 上传成功后的操作 } } }; </script> ``` 3. 在Express项目中安装express-fileupload和jsonserver: ```bash npm install express-fileupload jsonserver ``` 4. 创建一个Express路由,用于处理图片上传的请求: ```javascript const express = require('express'); const fileUpload = require('express-fileupload'); const app = express(); // 启用express-fileupload中间件 app.use(fileUpload()); // 处理图片上传的请求 app.post('/api/upload', (req, res) => { if (!req.files) { return res.status(400).send('No files were uploaded.'); } // 获取上传的文件 const sampleFile = req.files.sampleFile; // 将文件保存到指定位置 sampleFile.mv('/path/to/save/' + sampleFile.name, (err) => { if (err) { return res.status(500).send(err); } // 返回上传成功的信息 res.send('File uploaded!'); }); }); // 启动服务器 app.listen(3000, () => { console.log('Server is running on port 3000'); }); ``` 5. 启动jsonserver,用于模拟数据的请求和响应: ```bash json-server --watch db.json --port 4000 ``` 6. 创建一个db.json文件,用于存储上传成功的图片信息: ```json { "images": [] } ``` 现在,你就可以在Vue应用中使用这个上传组件,并将上传成功的图片信息存储到db.json文件中了。记得将图片保存路径修改为你想要存放的指定位置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值