node服务器处理常见场景

常用的场景

日志记录

常用的express中间件log4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// 配置
log4js.configure({
// 出口
appenders: {
sql: {
type: 'dateFile', //file普通文件,dateFile日期文件在备份时会在文件名中加入日期
filename: path.resolve(__dirname, 'logs', 'sql', 'logging.log'), //写入文件地址
maxLogSize: 2 ** 20, // 一个文件写入的最大字节数,超过之后会自动备份到其他文件
keepFileExt: true, //保留备份文件的后缀名
// daysToKeep: 0, // 文件会保留多少天,默认为0,一直保留
// 写入的格式
layout: {
type: 'pattern', //pattern是自定义样式
pattern: '%c: %d{yyyy-MM-dd hh:mm:ss} %p %m%n' //写入文件的格式

}
},
default: {
type: 'stdout', //标准控制台输出
},
},
// 分类
categories: {
sql: {
appenders: ["sql"], //该出口使用出口sql的配置
level: 'all', //级别配置
},
default: {
appenders: ["default"], //该出口使用出口default的配置
level: 'all', //级别配置
},

}
})

//程序要退出时运行shutdown记录完日志
process.on('exit', () => {
log4js.shutdown();
})

const sqlLogger = log4js.getLogger('sql');
const logger = log4js.getLogger();

module.exports = {
sqlLogger,
logger,
}

文件上传

客户端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<body>
<p>
<input type="file" name="img" multiple>
</p>
<p>
<button>上传</button>
</p>
<script>
const inputFile = document.querySelector('[name=img');

function upload() {
const formData = new FormData(); //构建一个form-data格式的消息体
for (const img of inputFile.files) {
formData.append('img', img, img.name);
}
fetch('/api/upload', {
method: 'POST',
body: formData,
})
.then((resp) => resp.text())
.then((resp) => {
console.log(resp)
})
}


document.querySelector('button').onclick = upload;
</script>
</body>

服务端

使用express中间件multer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// 文件上传

const express = require('express');
const multer = require('multer');
const path = require('path');
const getMsg = require('../getSendResult');

const router = express.Router();

/**
* 要存储的文件地址和文件名
*/
const storage = multer.diskStorage({
destination: function(req, file, cb) {
const distName = path.resolve(__dirname, '../../public/upload');
cb(null, distName)
},
filename: function(req, file, cb) {
// 文件名等于时间戳-xyqihsz后缀名
const filename = Date.now() + '-xyqihsz' + path.extname(file.originalname);
cb(null, filename)
}
})


function fileFilter(req, file, cb) {
// 允许上传的文件类型
const whiteList = ['.jpg', '.png', '.jpeg', '.gif'];
if (whiteList.includes(path.extname(file.originalname))) {
cb(null, true);
} else {
//处理异常
cb(new Error(`you upload file extname '${path.extname(file.originalname)}' is not support!`))
}
}

const upload = multer({
storage,
limits: {
fileSize: 150 * 1024,
}, //限制文件大小
fileFilter
})


router.post('/', upload.single('img'), (req, res) => {
res.send(getMsg.getResult({
url: 'upload/' + req.file.filename,
}))
})

module.exports = router;

文件下载

1
2
3
4
5
6
7
8
9
10
11
12
13
// 文件下载
const express = require('express');
const path = require('path');

const router = express.Router();

router.get('/:filename', (req, res) => {
const filePath = path.resolve(__dirname, '../../public/downloadResource/', req.params.filename);
// filePath下载文件的路径,req.params.filename下载时默认保存的文件名
res.download(filePath, req.params.filename);
})

module.exports = router;

图片加水印

使用jimp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
const jimp = require('jimp');
const path = require('path');


/**
* 给一张图片加水印
* @param {*} waterFile 水印图片地址
* @param {*} originFile 原图片地址
* @param {*} targetFile 加完水印后图片的存储地址
* @param {*} proportion 水印占原图的比例,是多少分之一
* @param {*} marginProportion 水印距离原图边界占原图的比例
*/
async function mark(
waterFile,
originFile,
targetFile,
proportion = 10,
marginProportion = 0.01
) {
const [water, origin] = await Promise.all([
jimp.read(waterFile),
jimp.read(originFile),
]);

// 对水印图片进行缩放
const curProportion = origin.bitmap.width / water.bitmap.width;
water.scale(curProportion / proportion);

// 计算位置
const right = origin.bitmap.width * marginProportion;
const bottom = origin.bitmap.height * marginProportion;
const x = origin.bitmap.width - right - water.bitmap.width;
const y = origin.bitmap.height - bottom - water.bitmap.height;

// 写入水印
origin.composite(water, x, y, {
mode: jimp.BLEND_SOURCE_OVER,
opacitySource: 0.3,
});

await origin.write(targetFile);
}

生成二维码

使用qr-code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 生成二维码

const QrCode = require('qrcode');
const path = require('path');

const qrCodePath = path.resolve(__dirname, '../public/img', 'qrcode.jpg');


QrCode.toFile(qrCodePath, 'hsz my all!', {
color: {
dark: '#0ff',
light: '#000',
}
}, (error) => {
console.log(error)
})