# NodeServer **Repository Path**: gisxy123/NodeServer ## Basic Information - **Project Name**: NodeServer - **Description**: Node后台开发技术研究Demo - **Primary Language**: JavaScript - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-05-12 - **Last Updated**: 2021-11-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ### 这是一个JavaScript开发后台的实践Demo ### deno学习[https://github.com/chenshenhai/deno_note](https://github.com/chenshenhai/deno_note) ### Node热启动nodemon `npm install --global nodemon` 安装好后,启动js文件把node指令改成nodemon指令就行了,保存后自动重启node服务器 ### 并发测试autocannon ``` npm i -g autocannon //发起100请求测试 autocannon http://127.0.0.1:3001/ -c 100 ``` ### Deno@v1.0.0发布:2020-5-13 ![输入图片说明](https://images.gitee.com/uploads/images/2020/0520/104212_419e52c0_1652494.jpeg "bg2020012504.jpg") #### Deno 简介 Deno 是一个 JavaScript/TypeScript 的运行时,默认使用安全环境执行代码,有着卓越的开发体验。Deno 含有以下功能亮点: 默认安全。外部代码没有文件系统、网络、环境的访问权限,除非显式开启。 支持开箱即用的 TypeScript 的环境。 只分发一个独立的可执行文件(deno)。 有着内建的工具箱,比如一个依赖信息查看器(deno info)和一个代码格式化工具(deno fmt)。 有一组经过审计的 标准模块,保证能在 Deno 上工作。 脚本代码能被打包为一个单独的 JavaScript 文件。 Deno 是一个跨平台的运行时,即基于 Google V8 引擎的运行时环境,该运行时环境是使用 Rust 语言开发的,并使用 Tokio 库来构建事件循环系统。Deno 建立在 V8、Rust 和 Tokio 的基础上,它的架构如下: ![输入图片说明](https://images.gitee.com/uploads/images/2020/0520/104341_b3efb389_1652494.jpeg "aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy9qUW13VElGbDFWMGN5V1VkWWljT0F6M0F5Mk0xQkM0cWg3NXdMcEJQYmxxaWFTVnlWQmZ3VTlvQzkyamd1dmdPTTVBSVBUaWFMMzBOWE9NNHV2NHQwUDlndy82NDA.jpg") - Rust Rust 是由 Mozilla 主导开发的通用、编译型编程语言。设计准则为 “安全、并发、实用”,支持函数式、并发式、过程式以及面向对象的编程风格。Deno 使用 Rust 语言来封装 V8 引擎,通过 libdeno 绑定,我们就可以在 JavaScript 中调用隔离的功能。 - Tokio Tokio 是 Rust 编程语言的异步运行时,提供异步事件驱动平台,构建快速,可靠和轻量级网络应用。利用 Rust 的所有权和并发模型确保线程安全。Tokio 构建于 Rust 之上,提供极快的性能,使其成为高性能服务器应用程序的理想选择。在 Deno 中 Tokio 用于并行执行所有的异步 IO 任务。 - V8 V8 是一个由 Google 开发的开源 JavaScript 引擎,用于 Google Chrome 及 Chromium 中。V8 在运行之前将JavaScript 编译成了机器代码,而非字节码或是解释执行它,以此提升性能。更进一步,使用了如内联缓存(inline caching)等方法来提高性能。有了这些功能,JavaScript 程序与 V8 引擎的速度媲美二进制编译。在 Deno 中,V8 引擎用于执行 JavaScript 代码。 #### Deno VS Node ![输入图片说明](https://images.gitee.com/uploads/images/2020/0520/110906_cc528d34_1652494.png "Deno VS Node") #### Deno安装——Window版需要通过PowerShell安装 ``` iwr https://deno.land/x/install/install.ps1 -useb | iex deno --version deno 1.0.0 v8 8.4.300 typescript 3.9.2 ``` #### Deno HelloWorld ``` /** * helloworld HTTP服务 * @param opts {Deno.ListenOptions} */ async function simpleServer(opts: Deno.ListenOptions): Promise { // 创建TCP服务 const listener: Deno.Listener = Deno.listen(opts) as Deno.Listener; console.log("listening on", `${opts.hostname}:${opts.port}`); // 死循环监听TCP请求 while (true) { // 等待TCP连接 const conn: Deno.Conn = await listener.accept(); // 执行响应 const CRLF = "\r\n"; const bodyStr = "hello world!"; const res = [ `HTTP/1.1 200`, `content-length: ${bodyStr.length}`, ``, `${bodyStr}` ].join(CRLF); // 将HTTP报文字符串转成 二进制数据流 const encoder = new TextEncoder(); // 将HTTP二进制数据流写入TCP连接 await conn.write(encoder.encode(res)); conn.close(); } } simpleServer({ hostname: "127.0.0.1", port: 3001, }); ``` #### Deno运行 `deno run --allow-all denoDemo.ts` #### Deno常用命令——使用方式:deno [子命令] [子命令的flags(可以多个)] [参数args] ``` deno -h deno 1.0.0 A secure JavaScript and TypeScript runtime Docs: https://deno.land/std/manual.md Modules: https://deno.land/std/ https://deno.land/x/ Bugs: https://github.com/denoland/deno/issues To start the REPL: deno To execute a script: deno run https://deno.land/std/examples/welcome.ts To evaluate code in the shell: deno eval "console.log(30933 + 404)" USAGE: deno [OPTIONS] [SUBCOMMAND] OPTIONS: -h, --help Prints help information -L, --log-level Set log level [possible values: debug, info] -q, --quiet Suppress diagnostic output -V, --version Prints version information SUBCOMMANDS: bundle Bundle module and dependencies into single file cache Cache the dependencies completions Generate shell completions doc Show documentation for a module eval Eval script fmt Format source files help Prints this message or the help of the given subcommand(s) info Show info about cache or info related to source file install Install script as an executable repl Read Eval Print Loop run Run a program given a filename or url to the module test Run tests types Print runtime TypeScript declarations upgrade Upgrade deno executable to given version ENVIRONMENT VARIABLES: DENO_DIR Set deno's base directory (defaults to $HOME/.deno) DENO_INSTALL_ROOT Set deno install's output directory (defaults to $HOME/.deno/bin) NO_COLOR Set to disable color HTTP_PROXY Proxy address for HTTP requests (module downloads, fetch) HTTPS_PROXY Same but for HTTPS ``` #### Deno子命令 ##### deno run run 主要功能 - 编译ts成js代码和sourceMap文件,存在 $HOME/.deno/gen/ 目录下 - 并且js和 sourceMap文件 都是以hash值命名的 - 只要代码不做变更,都会一直执行编译后的文件 - 如果代码变更了,会重新执行编译,并且生成新的hash命名的js和sourceMap文件 run 权限相关flags - deno run --allow-net mod.ts 执行代码 允许直接使用网络权限 - deno run --allow-read mod.ts 执行代码 允许直接使用文件读权限 - deno run --allow-write mod.ts 执行代码 允许直接使用文件写权限 - deno run --allow-run mod.ts 执行代码 允许直接执行子程序 - deno run --allow-env mod.ts 执行代码 允许直接使用操作环境权限 - deno run --allow-run mod.ts 执行代码 允许执行子进程 - deno run --allow-hrtime mod.ts 执行代码 允许测量高分辨率时间 - deno run --allow-all mod.ts 执行代码 允许以上所有权限 run 其他flags - deno run -h 查看帮助文档 - deno run -D mod.ts 或 deno --log-debug 输出执行底层日志 - deno run --no-prompt mod.ts 执行代码时不显示提示 - deno run --v8-flags mod.ts 设置V8命令行参数 ##### 子命令 eval - 作用: - 直接执行脚本代码的字符串 例如:deno eval "console.log('hello world! ' + new Date().getTime())" ##### 子命令fetch - 作用: - 获取远程在线的依赖模块 - 说明: - 下载和编译远程依赖模块,并保存在本地 - 以及递归获取和编译模块的所有依赖 - 编译后无需运行代码 - 在后续项目程序应用相同远程代码时候,无需重新下载和编译,除非使用了--reload的flag - fetch 使用方式 ``` deno fetch https://deno.land/welcome.ts # 1. 将会把 https://deno.land/welcome.ts 下载到本地 # 2. 下载后会编译成js,缓存在本地 # 3. 再次执行 deno fetch https://deno.land/welcome.ts,将会直接从缓存获取 # 4. 本地其他项目如果有 import 'https://deno.land/welcome.ts' 的时候,将会直接从缓存获取 deno fetch --reload https://deno.land/welcome.ts # 1. 将会重新把 https://deno.land/welcome.ts 下载到本地 # 2. 下载后会编译成js,覆盖上一次的缓存 ``` ##### 子命令 fmt - 作用: - 自动格式化Deno项目JavaScript和TypeScript 源码格式 - fmt 使用方式 ``` deno fmt mod.ts # 将会格式化 mod.ts 的源码格式 ``` ##### 子命令 info - 作用: - 显示Deno项目代码文件的相关信息 - 说明: - local 支持显示文件在本地的绝对路径 - type 支持显示文件类型,主要支持 JavaScript, TypeScript 和 JSON 三种格式 - compiled 只支持TypeScript类型的文件,显示TypeScript编译后JavaScript代码文件在本地的绝对路径 - map 只支持TypeScript类型的文件,显示TypeScript编译后sourceMap文件在本地的绝对路径 - deps 支持显示文件里代码的依赖模块,并显示依赖树 - info 使用方式 `deno info mod.ts ` ### Express介绍 Express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用,和丰富的 HTTP 工具 Express 框架核心特性: * 可以设置中间件来响应 HTTP 请求; * 定义了路由表用于执行不同的 HTTP 请求动作; * 可以通过向模板传递参数来动态渲染 HTML 页面。 ### Express安装 `$ npm install express --save` * body-parser - node.js 中间件,用于处理 JSON, Raw, Text 和 URL 编码的数据; * cookie-parser - 这就是一个解析Cookie的工具。通过req.cookies可以取到传过来的cookie,并把它们转成对象; * multer - node.js 中间件,用于处理 enctype="multipart/form-data"(设置表单的MIME编码)的表单数据。 ``` $ npm install body-parser --save $ npm install cookie-parser --save $ npm install multer --save ``` ### Koa简介 [https://koa.bootcss.com/](http://https://koa.bootcss.com/) ### Koa教程[https://github.com/ChenShenhai/koa2-note/](https://github.com/ChenShenhai/koa2-note/) Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石。 通过利用 async 函数,Koa 帮你丢弃回调函数,并有力地增强错误处理。 Koa 并没有捆绑任何中间件, 而是提供了一套优雅的方法,帮助您快速而愉快地编写服务端应用程序。 ### Koa安装 `$ npm i koa` ### Koa应用程序 Koa 应用程序是一个包含一组中间件函数的对象,它是按照类似堆栈的方式组织和执行的。 Koa 类似于你可能遇到过的许多其他中间件系统,例如 Ruby 的 Rack ,Connect 等,然而,一个关键的设计点是在其低级中间件层中提供高级“语法糖”。 这提高了互操作性,稳健性,并使书写中间件更加愉快。这包括诸如内容协商,缓存清理,代理支持和重定向等常见任务的方法。 尽管提供了相当多的有用的方法 Koa 仍保持了一个很小的体积,因为没有捆绑中间件。 ### Koa的hello world ``` const Koa = require('koa'); const app = new Koa(); app.use(async ctx => { ctx.body = 'Hello World'; }); app.listen(3000); ``` ### 本地JSON文件操作 #### 查询 ``` var fs = require("fs"); function listUser(req,res){ fs.readFile( './datas/' + "users.json", 'utf8', function (err, data) { res.setHeader('Content-Type', 'text/html; charset=utf8'); if(err){ console.log(err); var result = { status: 404, message: "failed", data: err } res.jsonp(result); }else { console.log(data); var users = data.toString(); users = JSON.parse(users); var result = { status: 200, message: "success", data: users.data } res.jsonp(result); } }); } ``` #### 分页slice(s,p) ``` function getUserPage(p,s,req,res){ fs.readFile( './datas/users2.json', 'utf8', function (err, data) { res.setHeader('Content-Type', 'text/html; charset=utf8'); if(err){ console.log(err); //res.end("错误提示:"+err); var result = { status: 404, message: "failed", data: err } //res.end(JSON.stringify(pageUser)); res.jsonp(result); }else { var users = data.toString(); users = JSON.parse(users); //var length = users.data.length; var pageUser = users.data.slice(s*p,(p+1)*s); console.log('----------分页成功-------------'); var result = { status: 200, message: "success", data: pageUser } //res.end(JSON.stringify(pageUser)); res.jsonp(result); } }); } app.get('/getUserPage', function (req, res) { console.log(req.query); getUserPage(Number(req.query.p),Number(req.query.s),req,res); }) ``` #### 添加push ``` function addUser(params,req,res) { fs.readFile( './datas/users.json', 'utf8', function (err, data) { res.setHeader('Content-Type', 'text/html; charset=utf8'); if(err){ console.log(err); res.end("错误提示:"+err); }else { var users = data.toString();//将二进制的数据转换为字符串 users = JSON.parse(users);//将字符串转换为json对象 users.data.push(user);//将传来的对象push进数组对象中 users.total = users.data.length;//定义一下总条数,为以后的分页打基础 console.log(users.data); var str = JSON.stringify(users); //因为nodejs的写入文件只认识字符串或者二进制数,所以把json对象转换成字符串重新写入json文件中 fs.writeFile('./datas/users.json',str,function(err){ if(err){ console.error(err); res.end("添加失败"); } console.log('----------新增成功-------------'); res.end("添加成功"); }) } }); } ``` #### 删除splice() ``` function deleteUser(id,req,res) { fs.readFile( './datas/users.json', 'utf8', function (err, data) { res.setHeader('Content-Type', 'text/html; charset=utf8'); if(err){ console.log(err); res.end("错误提示:"+err); }else { var users = data.toString(); users = JSON.parse(users); for(var i = 0; i < users.data.length;i++){ if(id == users.data[i].id){ //console.log(person.data[i]) users.data.splice(i,1); } } users.total = users.data.length; var str = JSON.stringify(users); fs.writeFile('./datas/users.json',str,function(err){ if(err){ console.error(err); res.end("删除失败"); } console.log('----------删除成功-------------'); res.end("删除成功"); }) } }); } ``` #### 条件查询req.query ``` function getUser(id,req,res) { fs.readFile( './datas/users.json', 'utf8', function (err, data) { res.setHeader('Content-Type', 'text/html; charset=utf8'); if(err){ console.log(err); var result = { status: 404, message: "failed", data: err } res.jsonp(result); }else { var users = data.toString(); users = JSON.parse(users); var user; for(var i = 0; i < users.data.length;i++){ if(id == users.data[i].id){ user=users.data[i]; break; } } var result = { status: 200, message: "success", data: user } if(user==null) { result.status=201; result.message="failed"; result.data="该用户不存在"; } res.jsonp(result); } }); } app.get('/getUser',function(req,res){ getUser(req.query.user,req,res); }) ``` #### 更新 ``` function updateUser(id,params,req,res){ fs.readFile( './datas/users.json', 'utf8', function (err, data) { res.setHeader('Content-Type', 'text/html; charset=utf8'); if(err){ console.log(err); res.end("错误提示:"+err); }else { var users = data.toString(); users = JSON.parse(users); for(var i = 0; i < users.data.length;i++){ if(id == users.data[i].id){ for(var key in params) { if(users.data[i][key]) users.data[i][key]=params[key]; } } } users.total = users.data.length; var str = JSON.stringify(users); fs.writeFile('./datas/users.json',str,function(err){ if(err){ console.error(err); res.end("更新失败"); } console.log('----------更新成功-------------'); res.end("更新成功"); }) } }); } ``` ### MySQL数据库操作 #### 驱动安装 `$ cnpm install mysql` #### 连接使用 ``` // 创建数据库连接 const mysql = require('mysql') const conn = mysql.createConnection({ //host:'39.96.71.104', host:'localhost', user:'root', password:'arcgis', database:'nodedemo' }) ``` #### 查询 ``` // 根据ID 获取相关数据 app.get('/api/getusers',(req,res) => { conn.connect(); console.log("数据库连接成功 success") const sqlStr = 'select * from users ' conn.query(sqlStr,(err,results) => { if(err) return res.json({code:1,data:'获取数据失败',message:"失败"}) res.json({ code:0, data:results, message:"成功" }) }) }) ``` #### 添加 ``` app.get('/api/adduser',(req,res)=>{ conn.connect(); var addSql = "INSERT INTO users(UserId,UserName,RoleCode,PassWord,Phone,Position,Remark,Village,RiverRole,District,RiverLake,River,Time) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)"; console.log(moment(new Date()).format('YYYY-MM-DD HH:mm:ss')); var addSqlParams = [111111,'宋向阳',1,'123456','17792573252','','','','','','','',moment(new Date()).format('YYYY-MM-DD HH:mm:ss')]; conn.query(addSql,addSqlParams,function (err, result) { if(err) { res.json({code:1,data:'插入数据失败',message:err}) console.log("插入数据失败:"+err); return; }else { res.json({code:0,data:result.affectedRows,message:"成功"}); console.log("插入数据成功"); } }); }) ``` #### 使用客户端JSON参数添加 ``` // 创建 application/json 解析 var jsonParser = bodyParser.json(); app.post('/api/adduserpost',jsonParser,(req,res)=>{ conn.connect(); var addSql = "INSERT INTO users(UserId,UserName,RoleCode,PassWord,Phone,Position,Remark,Village,RiverRole,District,RiverLake,River,Time) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)"; //console.log(req.body); //console.log(req.body.UserId+req.body.UserName,req.body.Time); var addSqlParams=[req.body.UserId,req.body.UserName,req.body.RoleCode,req.body.PassWord,req.body.Phone,req.body.Position,req.body.Remark,req.body.Village,req.body.RiverRole,req.body.District,req.body.RiverLake,req.body.River,moment(req.body.Time).format('YYYY-MM-DD HH:mm:ss')]; conn.query(addSql,addSqlParams,function (err, result) { if(err) { res.json({code:1,data:'插入数据失败',message:err}) console.log("插入数据失败:"+err); return; }else { res.json({code:0,data:addSqlParams,message:"成功"}); console.log("插入数据成功"); } }); }) ``` #### 更新 ``` app.post('/api/updateuser',jsonParser,(req,res)=>{ conn.connect(); var modSql = 'UPDATE users SET UserName = ?,Phone = ? WHERE UserId = ?'; var modSqlParams=[req.body.UserName,req.body.Phone,req.body.UserId]; conn.query(modSql,modSqlParams,function (err, result) { if(err) { res.json({code:1,data:'更新数据失败',message:err}) console.log("更新数据失败:"+err); return; }else { res.json({code:0,data:modSqlParams,message:"成功"}); console.log("更新数据成功"); } }); }) ``` #### 删除 ``` //使用url传参 //http://localhost:8081/api/deleteuser?UserId=220193 //通过req.query接收 app.delete('/api/deleteuser',(req,res)=>{ conn.connect(); var delSql = 'DELETE FROM users where UserId =?'; console.log(req.query); var delParams=req.query.UserId; conn.query(delSql,delParams,function (err, result) { if(err) { res.json({code:1,data:'删除数据失败',message:err}) console.log("删除数据失败:"+err); return; }else { res.json({code:0,data:delParams,message:"成功"}); console.log("删除数据成功"); } }); }) ``` ### MongoDB操作 #### MongoDB常用命令 ``` $ mongoexport -d wsm -c users -o D:/users.json --type json //导出集合 $ mongoimport -d wsm -c users --file D:\temp\users.json //导入集合 $ mongodump -h localhost -d wsm -o d:\temp //备份 $ mongorestore -h localhost -d wsm -dir d:\temp\wsm //恢复 --drop(可选,先删除再恢复) ``` #### 安装驱动 ` $ npm install mongodb` #### 查询 ``` var express = require('express'); var app = express(); var bodyParser = require('body-parser'); // 创建 application/json 解析 var jsonParser = bodyParser.json(); // 创建数据库连接 var MongoClient = require('mongodb').MongoClient; var url = "mongodb://localhost:27017/wsm"; app.get('/api/getuser',(req,res) => { MongoClient.connect(url, { useNewUrlParser: true, useUnifiedTopology: true }, function(err, db) { if (err) { console.log( err ); var result = { status: 0, message: "fail", data: err } res.jsonp(result); } console.log("数据库连接成功"); var dbase = db.db("wsm"); var whParam=req.query.UserName; var whereStr = {"username" : whParam}; // 查询条件 dbase.collection("users").find(whereStr).toArray(function(err, data) { // 返回集合中所有数据 if (err) { console.log( err ); var result = { status: 0, message: "fail", data: err } res.jsonp(result); } console.log(data); if(data.length>0) { var result = { status: 1, message: "success", data: data } res.jsonp(result); }else { var result = { status: 0, message: "fail", data: "用户不存在" } res.jsonp(result); } db.close(); }) }) }) ``` #### 分页 ``` app.get('/api/getuserpage',(req,res) => { MongoClient.connect(url, { useNewUrlParser: true, useUnifiedTopology: true }, function(err, db) { if (err) { console.log( err ); var result = { status: 0, message: "fail", data: err } res.jsonp(result); } console.log("数据库连接成功"); var dbase = db.db("wsm"); var s=parseInt(req.query.skip); var l=parseInt(req.query.limit); //.skip()跳过 //.limit()取指定数量记录 //.sort()排序 :1升序-1降序 var mysort = { "roleid": -1 }; dbase.collection("users").find({}).skip(s).limit(l).sort(mysort).toArray(function(err, data) { // 返回集合中所有数据 if (err) { console.log( err ); var result = { status: 0, message: "fail", data: err } res.jsonp(result); } console.log(data); if(data.length>0) { var result = { status: 1, message: "success", data: data } res.jsonp(result); }else { var result = { status: 0, message: "fail", data: "用户不存在" } res.jsonp(result); } db.close(); }) }) }) ``` #### 左连接 ``` app.get('/api/getuserrole',(req,res) => { MongoClient.connect(url, { useNewUrlParser: true, useUnifiedTopology: true }, function(err, db) { if (err) { console.log( err ); var result = { status: 0, message: "fail", data: err } res.jsonp(result); } console.log("数据库连接成功"); var dbase = db.db("wsm"); var whParam=req.query.UserName //match实现过滤 //lookup实现左连接 dbase.collection("users").aggregate([ { $match : {"username" : whParam} }, {$lookup: { from: 'roles', // 右集合 localField: 'roleid', // 左集合 join 字段 foreignField: 'roleid', // 右集合 join 字段 as: 'userrole' // 新生成字段(类型array) } } ]).toArray(function(err, data) { // 返回集合中所有数据 if (err) { console.log( err ); var result = { status: 0, message: "fail", data: err } res.jsonp(result); } console.log(data); if(Array.isArray(data) && data.length>0) { var result = { status: 1, message: "success", data: data } res.jsonp(result); }else { var result = { status: 0, message: "fail", data: "用户不存在" } res.jsonp(result); } db.close(); }) }) }) ``` #### 添加 ``` app.post('/api/adduser',jsonParser,(req,res) => { MongoClient.connect(url, { useNewUrlParser: true, useUnifiedTopology: true }, function(err, db) { if (err) { console.log( err ); var result = { status: 0, message: "fail", data: err } res.jsonp(result); } console.log("数据库连接成功"); var dbase = db.db("wsm"); var newUser = req.body; // { // "_id": "5c1ca2363298b2d7015ce1e", // "username": "aaaaaa", // "password": "7c4a8d09ca3762af61e59520943dc26494f8941b", // "roleid": 6, // "email": "xx@126.com", // "description": "我是测试信息", // "team": "所有", // "xzqdm": [ // ], // "xzqmc": [ // ] // } //console.log(req.body.username); //insertMany插入多条 dbase.collection("users").insertOne(newUser,function(err, data) { if (err) { console.log( err ); var result = { status: 0, message: "fail", data: err } res.jsonp(result); } var result = { status: 1, message: "success", data: data } res.jsonp(result); //console.log(data); }) }) }) ``` #### 更新 ``` app.post('/api/updateuser',jsonParser,(req,res) => { MongoClient.connect(url, { useNewUrlParser: true, useUnifiedTopology: true }, function(err, db) { if (err) { console.log( err ); var result = { status: 0, message: "fail", data: err } res.jsonp(result); } console.log("数据库连接成功"); var dbase = db.db("wsm"); var whereStr = {"username":req.body.username}; // 查询条件 var updateStr = {$set: { "email" : req.body.email}}; //updateone //updateMany更新多条 dbase.collection("users").updateMany(whereStr, updateStr,function(err, data) { if (err) { console.log( err ); var result = { status: 0, message: "fail", data: err } res.jsonp(result); } if(data.result.nModified>0) { var result = { status: 1, message: "success", data: data } res.jsonp(result); console.log("更新用户信息成功"+data.result.nModified+"条"); }else { var result = { status: 0, message: "fail", data: data } res.jsonp(result); console.log("更新用户信息失败,用户不存在"); } db.close(); }) }) }) ``` #### 删除 ``` app.post('/api/deleteuser',jsonParser,(req,res) => { MongoClient.connect(url, { useNewUrlParser: true, useUnifiedTopology: true }, function(err, db) { if (err) { console.log( err ); var result = { status: 0, message: "fail", data: err } res.jsonp(result); } console.log("数据库连接成功"); var dbase = db.db("wsm"); var whereStr = {"username":req.body.username}; //deleteOne //deleteMany删除多条 dbase.collection("users").deleteMany(whereStr,function(err, data) { if (err) { console.log( err ); var result = { status: 0, message: "fail", data: err } res.jsonp(result); } if(data.result.n>0) { var result = { status: 1, message: "success", data: data } res.jsonp(result); console.log("删除用户信息成功"+data.result.n+"条"); }else { var result = { status: 0, message: "fail", data: data } res.jsonp(result); console.log("删除用户信息失败"); } db.close(); }) }) }) ``` ### 文件上传 Express默认并不处理HTTP请求体中的数据,对于普通请求体(JSON、二进制、字符串)数据,可以使用 **body-parser** 中间件。而文件上传(multipart/form-data请求),可以基于请求流处理,也可以使用formidable模块或Multer中间件。 #### Multer中间件 Multer是Express官方推出的,用于Node.jsmultipart/form-data请求数据处理的中间件。 它基于busboy构建,可以高效的处理文件上传,但并不处理multipart/form-data之外的用户请求。 #### 安装及使用 `npm install multer --save` Multer在解析完请求体后,会向Request对象中添加一个body对象和一个file或files对象(上传多个文件时使用files对象 )。其中,body对象中包含所提交表单中的文本字段(如果有),而file(或files)对象中包含通过表单上传的文件。 #### formidable插件 用于解析表单数据,特别是文件上传 #### 安装 `npm install formidable --save` #### 文件上传 ``` var fs = require("fs"); var formidable = require('formidable'), http = require('http'), util = require('util'); http.createServer(function(req, res) { if (req.url == '/upload' && req.method.toLowerCase() == 'post') { var form = new formidable.IncomingForm({ encoding:"utf-8", uploadDir:"./upload_tmp", //文件上传地址 keepExtensions:true //保留后缀 }); // var form = new multiparty.Form({ // encoding:"utf-8", // uploadDir:"./upload_tmp", //文件上传地址 // keepExtensions:true //保留后缀 // }) form.parse(req, function(err, fields, files) { res.writeHead(200, {'content-type': 'text/plain'}); res.write('received upload:\n\n'); res.end(util.inspect({fields: fields, files: files})); var obj ={}; Object.keys(fields).forEach(function(name) { //console.log('name:' + name+";filed:"+fields[name]); obj[name] = fields[name]; }); Object.keys(files).forEach(function(name) { console.log('name:' + name+";file:"+files[name].path); obj[name] = files[name]; let timestamps = Math.round(new Date().getTime() / 1000).toString(); let newPath='./upload_tmp/'+timestamps+files[name].name; fs.rename(files[name].path, newPath, function (err) { if(err) { var result = { status: 0, message: "上传失败", data: err } res.end(result); }else { var result = { status: 1, message: "上传成功", data: files[name].name } res.end(result); } }) console.log(files[name].path); }); //var oldName = files.file.path; }); return; } // show a file upload form res.writeHead(200, {'content-type': 'text/html'}); res.end( '
'+ '
'+ '
'+ ''+ '
' ); }).listen(8888); ``` #### 接口调用 ![输入图片说明](https://images.gitee.com/uploads/images/2020/0519/162332_8280b5fe_1652494.png "1589876209(1).png") ### 模块和路由