Node + Express 后台开发 —— 上传、下载和发布
上传、下载和发布
前面我们已经完成了数据库的增删改查
,在弄一个上传
图片、下载
csv,一个最简单的后台开发就已完成,最后部署
即可。
上传图片
需求
需求
:做一个个人简介
的表单提交,有昵称
、简介
和头像
。后端能接收数据并保存到数据库。
接收不到数据
用 amis-editor
(amis 低代码编辑器,更多了解请看这里)绘制一个如下界面:
前端上传文件使用 InputFile
的手动上传。配置如下:
{
"type": "input-file",
"name": "file",
"label": "File",
"accept": "*",
"asBlob": true
}
后端定义一个路由:
// 个人简介
// http://localhost:3000/users/upload
router.post('/upload', function(req, res, next) {
console.log('req', req.body)
res.send({"status":0,"msg":"","data":{}});
});
输入信息后提交,后端 req.body
是空对象,说明无法接收数据:
req {}
POST /users/upload 200 6.230 ms - 31
前端传输数据如下:
如果前端不传文件
,后端 req.body 则能正常接收数据:
req { nickname: 'pjl', introduction: 'i am pjl', file: '' }
POST /users/upload 200 26.287 ms - 31
Tip:Content-Type 用于指示资源的 MIMIE 类型,请求中,客户端告诉服务器实际发送的数据类型。相应中,告诉客户端发送的内容的内容类型。不传文件请求头的 Content-Type 是 Content-Type: application/json
;传了文件,请求头的 Content-Type 是 Content-Type: multipart/form-data; boundary=----
。需要在表单中进行文件上传时,就需要使用该格式:multipart/form-data
。
multer
Multer 是一个 node.js 中间件,用于处理 multipart/form-data
类型的表单数据,它主要用于上传文件。
注:Multer 不会处理任何非 multipart/form-data 类型的表单数据
安装 multer
:
PS E:\pjl-back-end> npm install --save multer
added 17 packages, and audited 119 packages in 18s
3 packages are looking for funding
run `npm fund` for details
4 vulnerabilities (3 high, 1 critical)
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
使用 multer:
PS E:\pjl-back-end> git diff routes/users.js
+const multer = require('multer')
+// 启动服务后,自动在 public 下创建 uploads 文件夹
+const upload = multer({ dest: 'public/uploads/' })
+// 一旦请求过来,就会先经过中间件把接收到的图片存入 uploads 文件夹中,然后在到下一步
+// file 是前端文件的 name。由于这里是一张图片,所以用 single 方法。多张图片的使用请看文档
+router.post('/upload', upload.single('file'), function(req, res, next) {
+ // req.body 将具有文本域数据,如果存在的话
+ console.log(req.body)
+ // req.file 是 `file` 文件的信息
+ console.log(req.file)
res.send({"status":0,"msg":"","data":{}});
});
启动服务后,会自动
在 public 下创建 uploads
文件夹。输入昵称、简介和头像,点击提交。头像文件会重命名并上传到 uploads 中,通过 req.body
可以取得昵称和简介,通过 req.file
可以取得文件信息。后续存入数据库的操作笔者就不在进行,无非就是通过 token 取得用户 id,然后将昵称、简介和头像路径传给 services,通过 model 保存到数据库。
Tip:虽然文件没有了后缀(.png),通过chrome 直接访问图片路径(http://localhost:3000/uploads/36d8bda3160d8d09e81b167de1969b47
)会自动下载,把图片路径给到 image 是可以正常使用。
下载csv
需求
需求
:点击导出全部
按钮,发起请求,通过后端直接下载 csv 文件,里面是表格数据。
实现
安装 json2csv
包,用于将数据库中查询的 json 转为 csv:
PS E:\pjl-back-end> npm install json2csv
added 4 packages, and audited 123 packages in 4s
3 packages are looking for funding
run `npm fund` for details
4 vulnerabilities (3 high, 1 critical)
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
PS E:\pjl-back-end>
安装 iconv-lite
用于编码转换:
PS E:\pjl-back-end> npm i iconv-lite
added 2 packages, changed 1 package, and audited 125 packages in 3s
3 packages are looking for funding
run `npm fund` for details
4 vulnerabilities (3 high, 1 critical)
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
新建 utils.js,导出 downloadResource
方法用于下载 csv:
// E:\pjl-back-end\libs\utils.js
const Parser = require('json2csv').Parser;
const downloadResource = (res, fileName, fields, data) => {
const json2csv = new Parser({ fields });
const csv = json2csv.parse(data);
// iconv-lite: Pure JS character encoding conversion 转码,防止中文乱码
const iconv = require('iconv-lite');
const newCsv = iconv.encode(csv, 'gbk')
res.header('Content-Type', 'text/csv');
res.attachment(fileName);
return res.send(newCsv);
}
module.exports = {
downloadResource,
}
在任意路由中增加下载的处理请求:
const downloadResource = require('../libs/utils').downloadResource;
router.get('/download', function(req, res, next) {
// 列名
const fields = [
{
label: '姓名',
value: 'name'
},
{
label: '年龄',
value: 'age'
},
];
// 模拟从数据库查询出的数据
const data = [
{ "name":"peng 彭", "age": 18},
{ "name":"jia 加", "age": 19},
{ "name":"li 李", "age": 20},
{ "name":"pjl 彭加李", "age": 21},
];
return downloadResource(res, 'users.csv', fields, data);
});
重启服务,浏览器输入 localhost:3000/users/download
回车后会自动下载 csv 文件。双击打开 csv,效果如下:
如果不转码处理,这里 csv 中的中文就会乱码。
疑惑
:网上说 gbk和utf8都是都能编码中英文。将 gbk 改为 utf8
,在 win7 中打开 csv 仍旧乱码,或许是win7 中打开csv是gbk,得保持客户端和服务器编码一致?
发布
pm2
假如 node 项目已经开发完毕,得将应用部署到服务器中。
直接使用 node app.js
一旦关闭终端,服务就会中断
虽然也可以使用 node app.js &
后台启动服务,但也有很多不足,比如重新发布代码不会自动生效
Tip: windows 下关闭后台启动的服务,比如端口是 3000
PS E:\pjl-back-end> netstat -ano|findstr 3000
TCP 0.0.0.0:3000 0.0.0.0:0 LISTENING 12384
TCP [::]:3000 [::]:0 LISTENING 12384
TCP [::1]:3000 [::1]:10229 TIME_WAIT 0
TCP [::1]:10230 [::1]:3000 TIME_WAIT 0
PS E:\pjl-back-end> taskkill /PID 12384 /F
成功: 已终止 PID 为 12384 的进程。
nodemon app.js
常用于开发环境
笔者这里使用 pm2。有如下好处:
- 监控服务资源
- 发布代码、宕机后会自动重启
- 比如你的是cpu 是4核,也能充分利用
- 能查看日志
体验 pm2
全局安装 pm2
PS E:\pjl-back-end> npm install pm2 -g
npm WARN deprecated uuid@3.4.0: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.
added 184 packages, and audited 185 packages in 25s
12 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
PS E:\pjl-back-end> pm2 list
下面我们使用 pm2 启动服务:
Tip: 笔者由于环境问题,使用 npx 运行 pm2。你们可以省略。
查看版本
通过 pm2 --version
查看版本,说明安装成功:
PS E:\pjl-back-end> npx pm2 --version
5.3.0
启动服务
通过 pm2 start 入口文件
启动服务:
PS E:\pjl-back-end> npx pm2 start ./bin/www
[PM2] Starting E:\pjl-back-end\bin\www in fork_mode (1 instance)
[PM2] Done.
┌────┬────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──
────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├────┼────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──
────────┼──────────┤
│ 0 │ www │ default │ 0.0.0 │ fork │ 9904 │ 0s │ 0 │ online │ 0% │ 42.0mb │ Adm… │ disabled │
└────┴────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──
────────┴──────────┘
应用的 id
是 0,name
是 www,后续删除、启动和重启应用使用 id 和 name 都可以。
↺
表示重启次数为0。后续重启应用会自动增加。
status 中的 online
表示已上线。
服务列表
通过 pm2 list
显示应用列表,比如目前有一个服务(www
)已启动(online
):
PS E:\pjl-back-end> npx pm2 list
┌────┬────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──
────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├────┼────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──
────────┼──────────┤
│ 0 │ www │ default │ 0.0.0 │ fork │ 9904 │ 2m │ 0 │ online │ 0% │ 57.9mb │ Adm… │ disabled │
└────┴────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──
────────┴──────────┘
重启服务
通过 pm2 restart id|name
重启服务:
// 通过 id 重启
PS E:\pjl-back-end> npx pm2 restart 0
Use --update-env to update environment variables
[PM2] Applying action restartProcessId on app [0](ids: [ '0' ])
[PM2] [www](0) ✓
┌────┬────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──
────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├────┼────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──
────────┼──────────┤
│ 0 │ www │ default │ 0.0.0 │ fork │ 12088 │ 0s │ 1 │ online │ 0% │ 41.9mb │ Adm… │ disabled │
└────┴────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──
────────┴──────────┘
// 通过 name 重启
PS E:\pjl-back-end> npx pm2 restart www
Use --update-env to update environment variables
[PM2] Applying action restartProcessId on app [www](ids: [ 0 ])
[PM2] [www](0) ✓
┌────┬────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──
────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├────┼────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──
────────┼──────────┤
│ 0 │ www │ default │ 0.0.0 │ fork │ 6648 │ 0s │ 2 │ online │ 0% │ 40.9mb │ Adm… │ disabled │
└────┴────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──
Tip: ↺
表示重启过几次了
应用详情
pm2 info www
查看 www 这个应用的详细信息:
PS E:\pjl-back-end> npx pm2 info www
Describing process with id 0 - name www
┌───────────────────┬────────────────────────────────────────────────┐
│ status │ online │
│ name │ www │
│ namespace │ default │
│ version │ 0.0.0 │
│ restarts │ 2 │
│ uptime │ 62s │
│ script path │ E:\pjl-back-end\bin\www │
│ script args │ N/A │
│ error log path │ C:\Users\Administrator\.pm2\logs\www-error.log │
│ out log path │ C:\Users\Administrator\.pm2\logs\www-out.log │
│ pid path │ C:\Users\Administrator\.pm2\pids\www-0.pid │
│ interpreter │ node │
│ interpreter args │ N/A │
│ script id │ 0 │
│ exec cwd │ E:\pjl-back-end │
│ exec mode │ fork_mode │
│ node.js version │ 16.20.0 │
│ node env │ N/A │
│ watch & reload │ ✘ │
│ unstable restarts │ 0 │
│ created at │ 2023-05-09T07:28:11.550Z │
└───────────────────┴────────────────────────────────────────────────┘
Revision control metadata
┌──────────────────┬──────────────────────────────────────────┐
│ revision control │ git │
│ remote url │ N/A │
│ repository root │ E:\pjl-back-end │
│ last update │ 2023-05-09T07:28:12.179Z │
│ revision │ a02f7d6427fde5fdce41aff1626d31c19d80fcdf │
│ comment │ 取消数据库和登录标识 │
│ branch │ master │
└──────────────────┴──────────────────────────────────────────┘
Actions available
┌────────────────────────┐
│ km:heapdump │
│ km:cpu:profiling:start │
│ km:cpu:profiling:stop │
│ km:heap:sampling:start │
│ km:heap:sampling:stop │
└────────────────────────┘
Trigger via: pm2 trigger www <action_name>
Code metrics value
┌────────────────────────┬───────────┐
│ Used Heap Size │ 20.15 MiB │
│ Heap Usage │ 89 % │
│ Heap Size │ 22.64 MiB │
│ Event Loop Latency p95 │ 2.04 ms │
│ Event Loop Latency │ 0.08 ms │
│ Active handles │ 4 │
│ Active requests │ 0 │
└────────────────────────┴───────────┘
Divergent env variables from local env
Add your own code metrics: http://bit.ly/code-metrics
Use `pm2 logs www [--lines 1000]` to display logs
Use `pm2 env 0` to display environment variables
Use `pm2 monit` to monitor CPU and Memory usage www
监控应用
通过 pm2 monit id|name
监控应用程序:
PS E:\pjl-back-end> npx pm2 monit www
┌─ Process List ───────────────────────── ─ www Logs ─────────────────┐┌─ Logs ───────────────────────────────────────────────
[ 0] www Mem: 59 MB CPU: 0 % online │www > 错误信息
│ │www > GET /users/testlog 304 1.186 ms - -
│ │www > 信息
│ │www > 错误信息
│ │www > GET /users/testlog 304 1.837 ms - -
│ │www > 信息
│ │www > GET /users/testlog 304 0.914 ms - -
│ │www > 错误信息
│ │www > 信息
│ │www > 错误信息
│ │www > GET /users/testlog 304 1.369 ms - -
│ │www > 信息
│ │www > 错误信息
│ │www > GET /users/testlog 304 1.733 ms - -
│ │www > 信息
│ │www > 错误信息
│ │www > GET /users/testlog 304 3.095 ms - -
└─────────────────────────────────────────────────────────────────┘└────────────────────────────────────────────
┌─ Custom Metrics ────────────────────────────────────────────────┐┌─ Metadata ──────────────────────────────────────────────
│Used Heap Size 20.94 MiB │App Name www
│Heap Usage 91.45 % │Namespace default
│Heap Size 22.89 MiB │Version 0.0.0
│Event Loop Latency p95 9.12 ms │Restarts 2
│Event Loop Latency 0.14 ms │Uptime 2m
└─────────────────────────────────────────────────────────────────┘└────────────────────────────────────────────
left/right: switch boards | up/down/mouse: scroll | Ctrl-C: exit To go further check out https://pm2.io/
Tip:日志信息也会同步输出,日志就是console.log 或 console.error输出的内容,下文配置 pm2
会讲到。
停止应用
通过 pm2 stop id|name
停止服务:
PS E:\pjl-back-end> npx pm2 stop www
[PM2] Applying action stopProcessId on app [www](ids: [ 0 ])
[PM2] [www](0) ✓
┌────┬────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──
────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├────┼────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──
────────┼──────────┤
│ 0 │ www │ default │ 0.0.0 │ fork │ 0 │ 0 │ 2 │ stopped │ 0% │ 0b │ Adm… │ disabled │
└────┴────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──
────────┴──────────┘
关闭并删除应用
通过 pm2 delete id|name
关闭并删除应用:
PS E:\pjl-back-end> npx pm2 delete www
[PM2] Applying action deleteProcessId on app [www](ids: [ 0 ])
[PM2] [www](0) ✓
┌────┬───────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────
┬──────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
└────┴───────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────
┴──────────┴──────────┘
稳定的服务
比如笔者写一个如下服务 app2.js:
// app2.js
const http = require('http')
const fs = require('fs')
const server = http.createServer()
const requestListener = (req, res) => {
const url = req.url
// 如果url是 '/',则返回主页
if(url === '/'){
res.end("home page")
}else if(url === '/b'){
res.end("page b")
}else if(url === '/error'){
throw new Error('故意报错')
}
}
server.on('request', requestListener)
server.listen('3000', () => {
console.log('服务器已启动')
})
通过 node app2.js
启动服务后,访问 localhost:3000/error
故意报错,服务就会死掉,无法在响应其他请求:
PS E:\pjl-back-end> node app2.js
服务器已启动
E:\pjl-back-end\app2.js:13
throw new Error('故意报错')
^
Error: 故意报错
at Server.requestListener (E:\pjl-back-end\app2.js:13:15)
at Server.emit (node:events:513:28)
at parserOnIncoming (node:_http_server:998:12)
at HTTPParser.parserOnHeadersComplete (node:_http_common:128:17)
如果改用 pm2
启动服务:
PS E:\pjl-back-end> npx pm2 start app2.js
[PM2] Starting E:\pjl-back-end\app2.js in fork_mode (1 instance)
[PM2] Done.
┌────┬─────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬─
─────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├────┼─────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼─
─────────┼──────────┤
│ 0 │ app2 │ default │ 0.0.0 │ fork │ 12248 │ 0s │ 0 │ online │ 0% │ 40.2mb │ Adm… │ disabled │
└────┴─────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴─
─────────┴──────────┘
再次访问 localhost:3000/error
,通过 pm2 list
发现重启(↺
)次数从0变成了3,总之是重启了:
PS E:\pjl-back-end> npx pm2 list
┌────┬─────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬─
─────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├────┼─────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼─
─────────┼──────────┤
│ 0 │ app2 │ default │ 0.0.0 │ fork │ 12196 │ 25s │ 3 │ online │ 0% │ 39.7mb │ Adm… │ disabled │
└────┴─────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴─
访问 http://localhost:3000/
页面显示 home page
,说明服务正常,也较之前更稳定。
配置 pm2
需求
需求
:配置应用名称
、入口文件
、监控
、日志
、实例数
代码
项目根目录新建 pm2 配置文件 pm2.config.json
:
{
"apps": {
// 应用名称
"name": "spug-back-end",
// 入口文件
"script": "./bin/www",
// 监控。修改代码后自动生效
"watch": true,
// 排除某些文件的监控
"ignore_watch": [
"node_modules",
"logs"
],
// 错误日志。通过 console.error() 输出
"error_file": "logs/error.log",
// 自定义日志。通过 console.log() 输出
"out_file": "logs/custom.log",
// 给日志添加时间。否则你得这么写 console.log('信息...', '2023-05-09 16:25:00')
// YYYY不要小写
"log_date_format": "YYYY-MM-DD HH:mm:ss",
// cpu 核数。不要超过服务器的 cpu 核数
// 笔者 cpu 核数是 2,这样会启动 2 个服务,能更好的利用服务器资源。
"instances": 2
}
}
修改 package.json(pm2 指定配置文件
启动服务):
// package.json
"scripts": {
"start": "nodemon ./bin/www",
+"pro": "pm2 start ./pm2.config.json"
},
增加如下路由,用于测试日志
:
// localhost:3000/users/testlog
router.get('/testlog', function(req, res, next) {
// 输出到自定义日志中
console.log('信息');
// 输出到错误日志中
console.error('错误信息');
res.send({"status":0,"msg":"123","data":{}});
});
测试
通过 npm run pro
启动服务:
PS E:\pjl-back-end> npm run pro
> pjl-back-end@0.0.0 pro
> pm2 start ./pm2.config.json
[PM2][WARN] Applications spug-back-end not running, starting...
[PM2] App [spug-back-end] launched (2 instances)
┌────┬──────────────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬───
───────┬──────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├────┼──────────────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼───
───────┼──────────┼──────────┤
│ 0 │ spug-back-end │ default │ 0.0.0 │ cluster │ 12496 │ 0 │ 1 │ stopped │ 0% │ 0b │ Adm… │ enabled │
│ 1 │ spug-back-end │ default │ 0.0.0 │ cluster │ 11436 │ 0 │ 1 │ stopped │ 0% │ 0b │ Adm… │ enabled │
└────┴──────────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴───
───────┴──────────┴──────────┘
// 启动后立刻执行
PS E:\pjl-back-end> npx pm2 list
┌────┬──────────────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬───
───────┬──────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├────┼──────────────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼───
───────┼──────────┼──────────┤
│ 0 │ spug-back-end │ default │ 0.0.0 │ cluster │ 1396 │ 14s │ 1 │ online │ 0% │ 58.7mb │ Adm… │ enabled │
│ 1 │ spug-back-end │ default │ 0.0.0 │ cluster │ 1704 │ 14s │ 1 │ online │ 0% │ 58.7mb │ Adm… │ enabled │
└────┴──────────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴───
───────┴──────────┴──────────┘
PS E:\pjl-back-end>
应用名是 spug-back-end
。
启动了两个应用,说明 "instances": 2
已生效。
logs 文件夹中生成了4个日志文件(每个cpu核就是两个),文件名也是我们配置的,目前日志内容都为空:
$ ll logs
total 0
-rw-r--r-- 1 Administrator 197121 0 May 9 16:40 custom-0.log
-rw-r--r-- 1 Administrator 197121 0 May 9 16:40 custom-1.log
-rw-r--r-- 1 Administrator 197121 0 May 9 16:40 error-0.log
-rw-r--r-- 1 Administrator 197121 0 May 9 16:40 error-1.log
访问 http://localhost:3000/
页面显示正常:
Express
Welcome to Express
再次查看日志发现 custom-1.log
有内容,记录了着请求的详细信息。例如时间
、请求的资源(/stylesheets/style.css
):
Administrator@3L-WK-10 MINGW64 /e/pjl-back-end (master)
$ ll logs
total 1
-rw-r--r-- 1 Administrator 197121 0 May 9 16:40 custom-0.log
-rw-r--r-- 1 Administrator 197121 144 May 9 16:42 custom-1.log
-rw-r--r-- 1 Administrator 197121 0 May 9 16:40 error-0.log
-rw-r--r-- 1 Administrator 197121 0 May 9 16:40 error-1.log
Administrator@3L-WK-10 MINGW64 /e/pjl-back-end (master)
$ cat logs/custom-1.log
2023-05-09 16:42:35: GET / 304 21.595 ms - -
2023-05-09 16:42:35: GET /stylesheets/style.css 304 3.358 ms - -
修改某请求响应:
$ git diff routes/index.js
router.get('/', function(req, res, next) {
- res.render('index', { title: 'Express' });
+ res.render('index', { title: 'Express2' });
});
再次访问 http://localhost:3000/
修改信息自动生效:
Express2
Welcome to Express2
通过 npx pm2 list
发现服务自动重启了(↺ 1 -> 3
):
PS E:\pjl-back-end> npx pm2 list
┌────┬──────────────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬───
───────┬──────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├────┼──────────────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼───
───────┼──────────┼──────────┤
│ 0 │ spug-back-end │ default │ 0.0.0 │ cluster │ 13868 │ 89s │ 3 │ online │ 0% │ 60.5mb │ Adm… │ enabled │
│ 1 │ spug-back-end │ default │ 0.0.0 │ cluster │ 11792 │ 89s │ 3 │ online │ 0% │ 61.1mb │ Adm… │ enabled │
└────┴──────────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴───
再次查看日志,发现 custom-0.log 也有数据了,这里其实间接说明了一个负载均衡
的问题,这两个应用都能提供服务。
$ ll logs
total 2
-rw-r--r-- 1 Administrator 197121 228 May 9 16:46 custom-0.log
-rw-r--r-- 1 Administrator 197121 144 May 9 16:42 custom-1.log
-rw-r--r-- 1 Administrator 197121 0 May 9 16:40 error-0.log
-rw-r--r-- 1 Administrator 197121 0 May 9 16:40 error-1.log
接着访问输出日志的请求:http://localhost:3000/users/testlog
,发现在同一时刻(16:54:47
)往 custom-0.log 输出了 信息
,在 error-0.log 中输出了 错误信息
:
$ git diff logs
--- a/logs/custom-0.log
+++ b/logs/custom-0.log
2023-05-09 16:53:56: GET /users/testlog 304 14.507 ms - -
+2023-05-09 16:54:47: 信息
+2023-05-09 16:54:47: GET /users/testlog 304 9.892 ms - -
--- a/logs/error-0.log
+++ b/logs/error-0.log
2023-05-09 16:53:56: 错误信息
+2023-05-09 16:54:47: 错误信息
Node + Express 后台开发 —— 上传、下载和发布的更多相关文章
- Node + Express 后台开发 —— 起步
Node + Express 后台开发 -- 起步 前面陆续学习了一下 node.npm.模块,也稍尝试 Express,感觉得换一个思路加快进行. 比如笔者对前端的开发已较熟悉,如果领导给一个内部小 ...
- node+express实现文件上传功能
在进行node web开发时,我们可能经常遇到上传文件的问题,这一块如果我们没有经验,可能会遇到很多坑,下面我将跟大家分享一下,实现文件上传的一些方式. 一.node+express文件上传的常用方式 ...
- biweb后台添加上传下载功能
1.数据库对应表添加字段 file varchar(100) 2.对应的后台 模块名/admin/addinfo.php里添加如下代码: //文件上传 if ((($_FILES[&quo ...
- Vue+axios+Node+express实现文件上传(用户头像上传)
Vue 页面的代码 <label for='my_file' class="theme-color"> <mu-icon left value="bac ...
- (数据科学学习手札114)Python+Dash快速web应用开发——上传下载篇
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...
- node express formidable 文件上传后修改文件名
//我是用php的思想来学习nodejs var express = require('express'); var router = express.Router(); var fs = requi ...
- 文件上传下载(C#,web,asp.net)
目的:在浏览器页面启动上传下载CS软件,实现文件的批量下载与上传. 技术路线: 开发上传下载客户端CS程序与注册程序,压缩放到服务器端指定位置: 开发服务器端程序用以接收上传请求,压缩放到服务器端: ...
- C# 文件上传下载功能实现 文件管理引擎开发
Prepare 本文将使用一个NuGet公开的组件技术来实现一个服务器端的文件管理引擎,提供了一些简单的API,来方便的实现文件引擎来对您自己的软件系统的文件进行管理. 在Visual Studio ...
- C#微信公众号开发系列教程六(被动回复与上传下载多媒体文件)
微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C ...
- SNF开发平台WinForm之六-上传下载组件使用-SNF快速开发平台3.3-Spring.Net.Framework
6.1运行效果: 6.2开发实现: 1.先在要使用的项目进行引用,SNF.WinForm.Attachments.dll文件. 2.在工具箱内新建选项卡->选择项,浏览找到文件SNF.WinFo ...
随机推荐
- 【StoneDB 模块介绍】服务器模块
[StoneDB 模块介绍]服务器模块 一.介绍 客户端程序和服务器程序本质上都是计算机上的一个进程,客户端进程向服务器进程发送请求的过程本质上是一种进程间通信的过程,StoneDB 数据库服务程序作 ...
- Repeater 绑定数据如何根据数据列的内容排序
可指定Repeater的数据源 从数据库查询时直接排序,而后绑定数据这样
- Markdown操作方法
Markdown学习 标题 三级标题 四级标题 字体 原本 hello,world! 斜体 hello,world! 加粗 hello,world! 斜体加粗 hello,world! 删除 hell ...
- Activiti7开发(四)-我的待办
目录 1. 查询登录用户的待办任务 2.审批 1. 查询登录用户的待办任务 private List<Task> queryMyTasks(){ String username = Sec ...
- 【LeetCode997】【哈希表】[Py/C#/Scala/Elixir/Kotlin/Rust/Ruby/Swift/PHP/Java/Go/C++/TS/Erlang/Racket/Dart] 一道统计入度出度的简单题目
可以看到,一般而言,Python最接近"想思路时写的伪代码" 目录 解题思路 代码 python3 C# scala elixir kotlin rust ruby swift p ...
- forEach如何终止循环
try { try { this.list.forEach(item => { ..... throw new Error('end') }) } catch(err) { console.lo ...
- 【随笔】Axios delete传递数组问题
pre { overflow-y: auto; max-height: 300px } img { max-width: 500px; max-height: 300px } Axios delete ...
- kafka rebalance你真的了解吗
介绍 今天主要分享一下 kafka 的 rebalance,在 kafka 中,rebalance 是一个十分重要的概念,很多时候引发的一些问题可能都是由于 rebalance 引起的,rebalan ...
- 鼎捷ERP二维码整体解决方案 Tiptop GP条码管理系统 鼎捷ERP移动解决方案 鼎捷条码扫描 鼎捷WMS仓库移动扫码 鼎捷安卓PDA扫码方案 Tiptop 出入库盘点出货条码扫码 提供源码
本人在ERP实施公司做顾问四五年,参与企业实施ERP十多个项目,非常熟悉企业ERP流程,在实施过程遇到众多问题,提出了不少根据企业具体情况的解决方案. 最近定制开发了一套适合企业的条码扫码平台,基于鼎 ...
- 我没能实现始终在一个线程上运行 task
前文我们总结了在使用常驻任务实现常驻线程时,应该注意的事项.但是我们最终没有提到如何在处理对于带有异步代码的办法.本篇将接受笔者对于该内容的总结. 如何识别当前代码跑在什么线程上 一切开始之前,我们先 ...