使用Node.js和MongoDB进行CRUD操作和文件上传

使用Node.js和MongoDB进行CRUD操作和文件上传

在计算机编程世界中,CRUD是四个操作Create(创建)、Read(读取)、Update(更新)和Delete(删除)的缩写。 Create(创建)、Read(读取)、Update(更新)和Delete(删除)(CRUD)是模型应该能够完成的四个基本功能。在RESTful应用中,CRUD通常对应POST、PUT、DELETE和GET等HTTP方法。每个数据库都需要调用一些函数,以便用户可以执行一些操作。这些操作由用户用于在数据库中对特定数据执行某些类型的查询。操作的基础是CRUD操作。使用Node.js框架及其包,以及MongoDB和Postman,将执行CRUD操作和文件上传。

使用Node.js和MongoDB进行CRUD操作和文件上传

在深入了解代码如何工作之前,让我们了解应用程序的先决条件。本地机器应具备作为先决条件安装的Node js、Postman和MongoDB

  • Node js (npm): 如果没有安装Node.js和npm,请访问官方链接安装Node.js并在终端上运行以下命令下载npm。
npm install npm@latest -g
  • Postman: Postman用于管理请求。它通过GUI在不复制和粘贴每个HTTP请求的情况下,帮助测试HTTP请求。前往官方链接免费下载Postman。
  • MongoDB: MongoDB是在CRUD操作中使用的数据库。如果您没有MongoDB账号,不用担心,本文也将提供逐步指导。

该项目需要使用MongoDB作为后端在Node.js中构建。通过API接口提供以下功能:

  • 从多部分表单上传CSV文件
  • 扫描上传的CSV并将其内容推送到MongoDB集合中
  • 对上述集合进行CRUD操作的API

上述API使用passport包进行基本身份验证来管理访问权限。

所使用的框架和运行环境: 以下是项目中使用的主要框架和运行环境。

  • Node.js
  • NPM包管理器
  • MongoDB
  • Postman

步骤1: 创建Node.js项目。在终端中输入以下命令。

npm init

在将代码写入终端后,您需要填写信息。为了默认设置,请在每个部分按下 ENTER 键。最后,您将在目录中获得一个名为package.json的文件。
使用Node.js和MongoDB进行CRUD操作和文件上传

此项目中使用了一些作为依赖项的包,包括express,express-session,bcryptjs,fast-csv,csvtojson,dotenv,multer,passport,passport-local和mongoose。 运行以下命令安装这些包。

使用Node.js和MongoDB进行CRUD操作和文件上传

步骤2: 设置服务器。要为应用程序设置服务器,创建两个文件,分别命名为 app.js.env 。app.js作为服务器文件,.env将帮助加载环境变量。

在.env文件中编写本地主机的端口号 PORT = “端口号” 并在 app.js 中写下以下代码来运行服务器。 。

const express = require('express');
const app = express();
const dotenv = require('dotenv');
 
dotenv.config();
 
app.use(express.json({limit: '20mb'}))
app.use(express.urlencoded({ extended: false, limit: '20mb' }))
 
/* Setting up server */
app.listen(process.env.PORT, function(){
    console.log("This server port is up and running ");
})

要访问路径文件夹,其中包含所有的请求,请输入以下命令 –

/* Initializing the path for routes */
app.use("/", require("./routes"));

目前的最终代码在 app.js 中将如下所示-

const express = require('express');
const app = express();
const dotenv = require('dotenv');
 
dotenv.config();
 
app.use(express.json({limit: '20mb'}))
app.use(express.urlencoded({ extended: false, limit: '20mb' }))
 
/* Initializing the path for routes */
app.use("/", require("./routes"));
 
/* Setting up server */
app.listen(process.env.PORT, function(){
    console.log("This server port is up and running ");
})

开始运行该应用的步骤:

打开终端并输入 “node app.js” 将启动服务器。

使用Node.js和MongoDB进行CRUD操作和文件上传

步骤3: 连接到MongoDB集合。如果您不知道如何连接到MongoDB,请按以下步骤操作,否则请跳过以下步骤 –

  1. 前往 MongoDB Atlas
  2. 设置一个账号
  3. 创建一个新项目
  4. 创建一个数据库(可能需要几分钟)
  5. 进入数据库访问并填写用户名、密码和IP地址部分(可以将当前IP地址设为默认)
  6. 点击连接并选择连接您的应用程序,系统将给您一个地址。复制该地址并粘贴到.env文件中

使用Node.js和MongoDB进行CRUD操作和文件上传

最终的.env文件将类似于这样 –

DB_CONNECT = "YOUR PATH"
PORT = "Port Number"

集合创建完成后,通过在app.js中编写以下代码将Node.js应用程序与MongoDB连接。

global.dbconn = "";
 
/* Connected the app with mongoose */
mongoose.connect(
    process.env.DB_CONNECT,
    { useNewUrlParser: true, useUnifiedTopology: true },
    (client, err) =>{
        try{
            console.log("Connected to db: " + client)
        }catch(err){
            console.log(err);
        }
    }
);

步骤4: 这一步描述了项目的流程结构。项目被划分为不同的部分。有一个 middleware 文件夹,里面包含 controller 、 routes 和 config 文件。在 others 文件夹中有一个虚拟的 CSV 文件用于上传。使用路由上传后,将会把 CSV 文件上传到 uploads 文件夹中。在每个部分中创建以下文件。

注意: csv_controller.js 和 csv.js 只是用来执行 CRUD 操作的程序。

注意: 不需要创建 csv copy.js,因为它只是一个复制 csv.js 的文件。

使用Node.js和MongoDB进行CRUD操作和文件上传

Schema: 简单地说,模式是整个数据库的骨架结构。它允许我们定义各种字段供用户输入。

步骤5: 为用户和CRUD操作创建一个模式。由于数据需要是动态的,我们将定义数据库的模式。

在 models: User.js

const mongoose = require('mongoose');
 
/* Creating the schema with name, email, password and date */
const UserSchema = new mongoose.Schema({
    name: {
      type: String,
      required: true
    },
    email: {
      type: String,
      required: true
    },
    password: {
      type: String,
      required: true
    },
    date: {
      type: Date,
      default: Date.now
    }
  });
   
  /* Exporting schema with collection as CrudOperations */
  const User = mongoose.model('User', UserSchema);
   
  module.exports = User;

创建一个名为User的模式,该模式接受名称,电子邮件,密码和日期作为其字段。

crud.js

const mongoose = require('mongoose');
 
/**
 * Creating the schema with username, identifier, 
   firstName, lastName and updated
 */
const crud = new mongoose.Schema({
    username:{
        type: String,
        required: true,
    },
    identifier: {
        type: Number,
        required: true,
    },
    firstName:{
        type:String,
        required: true,
    },
    lastName:{
        type:String,
        required: true,
    },
    updated: {
        type: Date,
        required:true,
        default: Date.now,
    }
});
 
/**
 * Exporting schema with collection as CrudOperations
 */
module.exports = mongoose.model('CrudOperations', crud);

在crud.js中创建一个带有接受字段username、identifier、firstName、lastName、updated的模式。

步骤6: 在每个组织中,拥有适当的身份验证和授权非常重要。为此,每个组织都会加入一层安全措施。文件auth.js和passport.js就是这样做的。但由于本文帮助执行CRUD操作和文件上传,我们不会深入探讨这方面。

文件名:auth.js

module.exports = {
    /**
     * Ensuring authentication
     */
    ensureAuthenticated: function(req, res, next) {
      if (req.isAuthenticated()) {
        return next();
      }
      req.flash('error_msg', 'Please log in to view that resource');
      res.redirect('/users/login');
    },
    forwardAuthenticated: function(req, res, next) {
      if (!req.isAuthenticated()) {
        return next();
      }
      res.redirect('/dashboard');      
    }
  };

auth.js文件检查用户是否登录了帐户。如果是,用户被授权查看页面,否则将被重定向到主页

FILENAME: passport.js

const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcryptjs');
 
// Load User model
const User = require('../models/User');
 
module.exports = function(passport) {
  passport.use(
    new LocalStrategy({ usernameField: 'email' }, (email, password, done) => {
      // Match user
      User.findOne({
        email: email
      }).then(user => {
        if (!user) {
          return done(null, false, { message: 'That email is not registered' });
        }
 
        // Match password
        bcrypt.compare(password, user.password, (err, isMatch) => {
          if (err) throw err;
          if (isMatch) {
            return done(null, user);
          } else {
            return done(null, false, { message: 'Password incorrect' });
          }
        });
      });
    })
  );
 
  passport.serializeUser(function(user, done) {
    done(null, user.id);
  });
 
  passport.deserializeUser(function(id, done) {
    User.findById(id, function(err, user) {
      done(err, user);
    });
  });
};

随着这两个文件,需要有会话变量和授权将护照(passport)包括到这个项目中。为此, app.js 被打开并初始化了护照中间件和会话(session)。

文件名: app.js

// Passport Config
require('./config/passport')(passport);
 
app.use(express.json({limit: '20mb'}))
app.use(express.urlencoded({ extended: false, limit: '20mb' }))
 
// Express session
app.use(
    session({
      secret: 'secret',
      resave: true,
      saveUninitialized: true
    })
);
   
  // Passport middleware
  app.use(passport.initialize());
  app.use(passport.session());

步骤7: 使用multer包创建一个中间件。要使用multer包,请在终端中写入以下命令。

npm install --save multer

封装 multer 帮助处理 multipart/form-data 数据,主要用于上传文件。Multer 会向请求对象添加一个 body 对象和一个文件对象或多个文件对象。body 对象包含了表单文本字段的值,文件对象或多个文件对象包含了通过表单上传的文件。

文件名:uploader.js

const path = require('path')
const multer = require('multer')
 
var storage = multer.diskStorage({
    destination: function(req, file, cb){
        cb(null, 'uploads/')
    },
    filename: function(req, file, cb){
        let ext = path.extname(file.originalname)
        cb(null, Date.now() + ext);
    }
})
 
var upload = multer({
    storage: storage,
    fileFilter: function(req, file, callback){
        if(
            file.minetype == "text/csv"
        ){
            callback(null, true)
        } else{
            console.log("Error in uploading")
            callback(null, false)
        }
    },
    limits: {
        fileSize: 1024 * 1024 * 2
    }
})
 
module.exports = upload

步骤8: 在使用passport和multer作为中间件进行认证后,需要完成文件上传和CRUD操作的路由和控制器。

在进行操作之前,首先需要初始化路由。为了做到这一点, 使用index.js 。

文件名:index.js

const express = require("express");
var router = express.Router();
 
/* Initializing other routes */
router.use("/", require("./csv"));
router.use('/', require('./users.js'));
 
module.exports = router;

使用护照验证时,用户的路由和控制器在users.js和user_controller.js中创建。

FILENAME: users.js

const express = require('express');
const router = express.Router();
const userController = require("../controller/user_controller")
/* Register router with passport package */
router.post('/register', userController.register);
   
/* Login router */
router.post('/login', userController.login);
 
/* Logout router  */
router.get('/logout', userController.logout);
 
module.exports = router;

它将注册和登录的路由设置为POST方法,并将注销系统设置为GET方法。在user_controller中。

文件名: user_controller.js

const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const passport = require('passport');
// Load User model
const User = require('../models/User');
const { forwardAuthenticated } = require('../config/auth');
 
exports.register = (req, res) => {
    console.log("Request: " + JSON.stringify(req.body))
    const { name, email, password, password2 } = req.body;
    let errors = [];
   
    /* If condition to check whether all credentials are filled */
    if (!name || !email || !password || !password2) {
      errors.push({ msg: 'Please enter all fields' });
    }
     
    /* If condition to check whether password 
    and password2 matches or not */
    if (password != password2) {
      errors.push({ msg: 'Passwords do not match' });
    }
   
    /* If condition to check in case password 
    length is greater than 3 or not */
    if (password.length < 3) {
      errors.push({ msg: 'Password must be at least 3 characters' });
    }
   
    if (errors.length > 0) {
      res.send('register error')
    } else {
     
    /* Checking if user exists */
      User.findOne({ email: email }).then(user => {
        if (user) {
          errors.push({ msg: 'Email already exists' });
          res.send('register user exists');
        } 
         
       /* Creating the user */
       else {
          const newUser = new User({
            name,
            email,
            password
          });
           
          /* Bcrypt hashing the password for user privacy */
          bcrypt.genSalt(10, (err, salt) => {
            bcrypt.hash(newUser.password, salt, (err, hash) => {
              if (err) throw err;
              newUser.password = hash;
              newUser
                .save()
                .then(user => {
                  res.send("Register Successful");
                })
                .catch(err => console.log(err));
            });
          });
        }
      });
    }
  }
 
exports.login = (req, res, next) => {
 
    /* Authenticating if login was successful or 
    not with the help of passport */
passport.authenticate('local', {
    successRedirect: res.send("Login Successful"),
    failureRedirect: res.send("Error in Login"),
    failureFlash: false
})(req, res, next);
}
 
exports.logout = (req, res) => {
    req.logout();
   /* Logging out */
    res.send("User Logout");
}

注册导出器首先检查提供的凭据是否正确。如果正确,则使用 bcrypt 对密码进行加密。 ****然后在模式中保存新用户。为了检查函数是否工作,使用 postman 发送一个请求进行注册、登录和注销。

注册: 使用 postman 发送一个 post 请求 http://localhost:3000/register

使用Node.js和MongoDB进行CRUD操作和文件上传

登录: 发送一个 post 请求 http://localhost:3000/login

使用Node.js和MongoDB进行CRUD操作和文件上传

注销: 注销发送一个 get 请求。

使用Node.js和MongoDB进行CRUD操作和文件上传

增删改查操作和文件上传: 使用文件 csv.js 和 csv_controller.js, 执行所有的增删改查操作和文件上传。调用各种API来实现不同的功能。例如, http://localhost:3000/fileUpload 用于上传CSV文件并将数据推送到Mongoose。同样地, http://localhost:3000/CRUDcreate, http://localhost:3000/CRUDread, http://localhost:3000/CRUDupdate, http://localhost:3000/CRUDdelete 分别用于其他增删改查操作,即CREATE, READ, UPDATE, DELETE。

创建: 我们将发送 post 请求。如名称所示,它们创建函数允许所有用户在数据库中输入新记录。对于关系型数据库,创建函数称为INSERT。在非关系型数据库(如MongoDB)中,提供了两种不同的选项来将文档插入集合中 – db.collection.insertOne()
db.collection.insertMany()。

文件名:csv.js

/* Creating a schema for crud operation C: Create */
router.post("/CRUDcreate",  forwardAuthenticated, csvController.create)

文件名:csv_controller.js

exports.create = async function(req, res){
    /* Initializing the schema and putting in CRUDcreate */
    const CRUDcreate = new CRUDoperations ({
        username: req.body.username,
        identifier:req.body.identifier,
        firstName: req.body.firstName,
        lastName: req.body.lastName
    });
 
    /* Try Catch */
    try{
        /* Saving the data in mongoose */
        const savedCRUD = await CRUDcreate.save();
        /* Sending the response back */
        res.status(200);
        res.send(savedCRUD);
    }catch(err){
        /* Sending the error back */
        res.status(400).send(err);
    }   
}

添加所需的包到文件中后,完成操作后,使用.save()将信息保存到数据库中。

使用Node.js和MongoDB进行CRUD操作和文件上传

阅读: CRUD操作中的阅读功能类似于搜索功能。它帮助用户搜索和检索特定数据的特定信息。在MongoDB中,我们使用db.collection.find()或db.collection.findOne()来检索信息。

文件名:csv.js

/* Router for CRUD operation R: read */
router.get("/CRUDread", csvController.read)

文件名:csv_controller.js

exports.read = function(req, res){
    /* Using find() for reading all the data */
    CRUDoperations.find({}, function(err, fetch){
        /* In case of error */
        if(err) res.status(400).send(err);
 
        /* Sending back the response */
        res.status(200).send(fetch);        
    });
}

使用Node.js和MongoDB进行CRUD操作和文件上传

更新: 更新函数用于修改MongoDB数据库中集合中的数据。要更改记录,用户可能需要修改多个字段。这需要仔细更新文档,因为在更新集合时所做的更改是永久且不可逆的。MongoDB中可以使用3种不同的方法进行更新- db.collection.updateOne(),db.collection.updateMany(),db.collection.replaceOne()。

文件名:csv.js

/* CRUD operation 'update' router */
router.post("/CRUDupdate", csvController.update)

文件名: csv_controller.js

exports.update = async function(req, res){
    /* Taking the id */
    let id = req.body._id;
 
    try{
        /* Using findByIdAndUpdate */
        const CRUDupdate = await CRUDoperations.findByIdAndUpdate({_id: id},
         
        /* Setting the value of identifier as 1967 of corresponding id */
        {$set:{
                identifier: 1969
              }
        },
        {
            useFindAndModify: false
        });
 
        /* Sending the response back to the server */
        res.status(200).send(CRUDupdate);
    }catch(err){
        /* Sending error back to the server */
        res.status(400).send(err);
    } 
}

使用Node.js和MongoDB进行CRUD操作和文件上传

删除: 最后一种CRUD操作是删除。顾名思义,它帮助我们从一个文档中删除一个集合。

db.collection.deleteOne()
db.collection.deleteMany()

文件名:csv.js

/* Router to perform delete of CRUD operations */
router.post("/CRUDdelete", csvController.delete)

文件名:csv_controller.js

exports.delete =  async function(req, res){
    /* Taking the id of the collection */
    let id = req.body._id;
 
    /* Using Try and catch for deletion */
    try{
        /* Using findbyIdAndRemove operation to remove 
        the data with corresponding id */
        const CRUDdel = await CRUDoperations.findByIdAndRemove(
        id, function(err, res){
            if (err){
                /* Sending error back to the server */
                res.status(400).send(err);
                console.log(err)
            }
            else{
                 
                /* Sending the response back to the server */
                console.log("Removed User : ", res);
            }
        },
        {
            useFindAndModify: false
        })
    }catch(err){
        res.status(400).send(err);
    }
}

使用Node.js和MongoDB进行CRUD操作和文件上传

文件上传: 如前所述,文件上传是通过multer包来完成的。

文件名: csv.js

const fileStorageEngine = multer.diskStorage({
    destination: (req, file, cb) => {
        cb(null, './uploads')
    },
    filename: (req, file, cb) => {
        cb(null, Date.now() + "--" + file.originalname);
    },
});
 
const upload = multer({ storage: fileStorageEngine });
 
router.post('/single', upload.single('fileUpload'), (req, res) => {
    console.log('single route')
    console.log('file:'+JSON.stringify(req.file));
    res.send("single file upload success");
}); 
 
 
router.post("/fileUpload",upload.single('fileCSV'), 
    csvController.fileupload)

文件名:csv_controller.js

exports.fileupload = function(req, res){
    console.log("Inside file Upload!!")
    console.log('single route')
    console.log('file:'+JSON.stringify(req.file.path));
 
 
    let stream = fs.createReadStream(req.file.path)     
         
    let csvData = [];
 
    let csvStream = fastcsv
        .parse()
        .on('error', error => console.error(error))
        .on("data", function(data) {
            //console.log("Data Parse: " + JSON.stringify(data))
            dt = data[0].split(',')
            //console.log("DT: " + dt[0])
            csvData.push({
                username: dt[0],
                identifier: dt[1],
                firstName: dt[2],
                lastName: dt[3]
            });
            //console.log((csvData));
        })
        .on("end", async function() {
            // remove the first line: header
            csvData.shift();
 
            // save to the MongoDB database collection
            try{
                console.log("client:" + CRUDoperations);
                let CRUDinsert = await CRUDoperations.insertMany(
                    csvData
                )
                console.log("CRUD Insert Many" + CRUDinsert)
                res.status(200).send(CRUDinsert);
 
            } catch(err){
                console.log("db error:"+err);
                res.status(400).send(err);
            }
            console.log(JSON.stringify(csvData));
        });
 
    stream.pipe(csvStream);
}

使用Node.js和MongoDB进行CRUD操作和文件上传

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程