从零开始,搭建一个简单的购物平台(四)

本文最后更新于:6 个月前

从零开始,搭建一个简单的购物平台(三): https://blog.csdn.net/time_____/article/details/105411636
项目源码(持续更新):https://gitee.com/DieHunter/myCode/tree/master/shopping

本篇文章延续上篇的登录界面搭建完成后,进行用户管理后端的编写,主要功能包括:

添加用户,上传头像

目录结构如下:

首先实现上传头像功能

上传文件流程:用户选择文件上传,服务端读取文件并生成唯一命名的缓存文件(二进制文件),将文件信息回传到前端,前端提交表单时将文件信息和用户信息一同上传至服务端,服务端读取对应文件,保存至public的img文件夹(此时生成的是图片文件),最后将图片路径存至数据库中

具体实现

  • 在controller文件夹下新建upload文件夹,在文件夹中新增upload.js用于上传头像,引入multer模块并进行文件暂存

    const router = require("express").Router();
    const Util = require("../../../utils/utils");
    var multer = require("multer");
    var upload = multer({
      dest: "./public/temp",//缓存目录
    });
    router.post(
      "/headPic",
      upload.single("headPic"),//单张图片,图片标识名
      Util.checkToken,//验证token
      (req, res) => {
        res.send({
          result: 1,
          msg: "上传成功",
          headPath: req.file,
        });
      }
    );
    
    module.exports = router;
  • 在router中添加upload.js的路由地址 app.use(“/upload”,upload);
    运行项目,做个测试,在postman中输入相对应地址和参数后点上传,服务端返回缓存文件信息并保存到缓存目录

  • 添加上传功能后,只是保证文件上传,还要把它转换成图片格式,所以在utils.js文件中新增几个方法(要引入fs模块),分别是:

  • 读取文件*

    static readPicFile(_file) {
       let { path, mimetype } = _file;//获取文件路径和文件类型
       let file = fs.readFileSync(path);//将文件转换成二进制
       let fileName =//用时间戳加随机数命名文件
         new Date().getTime() +
         parseInt(Math.random() * Math.random() * 1000000) +
         "." +
         mimetype.split("/")[1];
       this.delPicFile(path);//删除之前的缓存文件
       return this.writePicFile(file, fileName);//写文件
     }
  • 保存(写入)文件*

    static writePicFile(_file, _fileName) {
      let fileName = "./public/assets/img/" + _fileName;//文件路径
      fs.writeFileSync(fileName, _file);
      return fileName.split("./")[1];
    }
  • 删除文件*

    static delPicFile(_path) {
        fs.unlink(_path, (err) => {
          if (err) {
            console.log("删除失败");
          }
        });
      }
  • 全部完成后,上传文件也已完成

添加用户功能

  • 在users.js界面中调取之前写的command(数据库增,删,改,查操作)

  • 由于增加操作可能是移动端用户注册,所以暂时不加token验证,由于邮箱和用户名是唯一值,所以需要先进行查找用户

    let findRes = await findData(Mod, {
        $or: [
          {
            mailaddress: res._data.mailaddress,
            mailurl: res._data.mailurl,
          },
          {
            username: res._data.username,
          },
          {
            mailaddress: res._data.username,
          },
          {
            username: res._data.mailaddress + res._data.mailurl,
          },
        ],
      });
      if (findRes && findRes.length > 0) {
        res.send({
          result: 0,
          msg: "添加失败,用户已存在",
        });
        Util.delPicFile(res._data.headPic);
        return;
      }
  • 判断到无此用户时,将其添加到数据库中

    if (res._data.headPic) {
      res._data.headPic = Util.readPicFile(res._data.headPic || "") || "";//保存头像
    }
    res._data.time = Util.joinDate();//添加时间
    res._data.password = Util.createBcrypt(res._data.password);//盐加密
    res._data.isactive = true;
    let addRes = await addData(Mod, res._data);
    if (addRes) {
      res.send({
        result: 1,
        msg: "添加成功",
      });
      return;
    }
    Util.delPicFile(res._data.headPic);
    res.send({
      result: 0,
      msg: "添加失败",
    });
  • 完成之后用postman测试一下,后端提示添加成功,数据库也成功添加该用户

文章到此,头像上传,用户添加就已经全部实现

总结

前后端项目请求应进行节流处理(即限制用户多次快速单击提交按钮),前后端双重保险,即可提升用户体验,又减少服务端压力,由于此项目主要以功能为主,在细节方面没有十分注重,真实线上项目必须添加节流