node.js 几个功能插件使用总结

总结了项目上用到的几个小功能:multer 文件上传nodemailer 发送邮件、jwt-simple 登录验证、map API 获取位置信息。

文件上传

Multer

Multer 是一个 node.js 中间件,用于处理 multipart/form-data 类型的表单数据,它主要用于上传文件。

安装

npm i express multer

配置

multer(opts) 配置

const multer = require('multer');

const maxSize = 3 * 1024 * 1024; // 大小限制
const fileTypes = ['png', 'jpg', 'jpeg', 'webp', 'gif'].map(type => `image/${type}`); // 类型限制

const filedir = '/files/uploads'; // 文件保存路径

const configs = {
limits: {
fileSize: maxSize,
},
fileFilter: (req, file, cb) => {
const {mimetype} = file;
if (fileTypes.includes(mimetype)) {
cb(null, true);
} else {
cb(new Error('Allowed only .png, .jpg, .jpeg, .webp and .gif'), false);
}
},
};
  • storage:存储文件位置配置

  • limits:上传大小限制

  • fileFilter:文件过滤器,控制哪些文件可以被接受

const upload = multer({
storage: storage,
...configs,
}).single('file'); // 单个文件上传
  • .single(fieldname):接受一个以 fieldname 命名的文件。这个文件的信息保存在 req.file。

  • .array(fieldname[, maxCount]):接受一个以 fieldname 命名的文件数组。可以配置 maxCount 来限制上传的最大数量。这些文件的信息保存在 req.files。

  • .fields(fields):接受指定 fields 的混合文件。这些文件的信息保存在 req.files。fields 应该是一个对象数组,应该具有 name 和可选的 maxCount 属性。

  • .none():只接受文本域。

  • .any():接受一切上传的文件。文件数组将保存在 req.files。

storage 配置

const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, filedir);
},
filename: (req, file, cb) => {
const {name, _id} = req.user;
const ext = path.extname(req.file.originalname);
const filename = `${_id}_${name}${ext}`; // 保存文件名
cb(null, filename);
},
});
  • destination:文件存储文件夹,可以是 string 或 function,如果没有设置 destination,则使用操作系统默认的临时文件夹。

  • filename:用于确定文件夹中的文件名。

使用

app.post('/uploads', (req, res) => {
upload(req, res, error => {
if (error instanceof multer.MulterError) {
// MulterError
} else if (error) {
// error
}
// ok
})
});

发送邮件

发送邮件配置信息

const nodemailer = require('nodemailer');

const sendEmail = (to, token, redirect) => {
const transporter = nodemailer.createTransport({
host: 'smtp.qq.com', // 邮件发送服务器
port: 465, // 端口
secure: true, // 使用 TLS
auth: {
user: 'xxx@qq.com', // 发送者邮箱
pass: 'xxx', // 授权码
},
});
const url = redirect || LOGIN_REDIRECT;
const mailOptions = {
from: `from xxx@qq.com`, // sender address
to, // list of receivers
subject: 'subject', // Subject line
text: `text`, // plaintext body
html: `html`, // html body
};
// send mail with defined transport object
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return error;
}
return info;
});
};

使用

sendEmail(req.body.email);

jwt 登录

创建 jwt

const jwt = require('jwt-simple');

const jwtDecode = token => jwt.decode(token, TOKEN_SECRET);
const jwtEncode = token => jwt.encode(token, TOKEN_SECRET);

const createJWT = (user, delay = 1) => {
const payload = {
sub: user._id,
iat: moment().unix(),
exp: moment().add(delay, 'days').unix(),
};
return jwtEncode(payload);
};

登录

密码加密

const crypto = require('crypto');

const sha512 = (str, options) => crypto.createHmac('sha512', options.salt.toString()).update(str).digest('hex');

const shaPwd = password => sha512(password, {salt: SALT});

创建 token

const login = (db, req, res) => {
db.findOne({name: req.body.name}, '+password', (err, user) => {
if (!user) {
return res.status(400).send({message: '该邮箱尚未注册!'});
}
const psd = shaPwd(req.body.password);
if (user.password !== psd) {
return res.status(403).send({message: '密码错误!'});
}
return res.status(200).send({token: createJWT(user), message: '登录成功!', result: user});
});
};

请求验证中间件

const ensureAuthenticated = (req, res, next) => {
if (!req.header('Authorization')) {
return res.status(401).send({message: '用户未登录,请登录后操作!'});
}
const token = req.header('Authorization').split(' ')[1];
if (!token) {
return res.status(401).send({message: '用户未登录,请登录后操作!'});
}
let payload = null;
try {
payload = jwtDecode(token);
} catch (err) {
return res.status(401).send({message: err.message});
}
if (payload.exp <= moment().unix()) {
return res.status(401).send({message: '验证信息过期,请重新登录!'});
}
next();
};

获取客户端位置信息

使用百度地图 API 获取地理位置信息。

获取 ak

进入百度地图开放平台创建应用,应用类别选服务端,即可生成 ak 。

通过 ip 获取信息

const {request} = require('../utils/request');

const apiUrl = 'https://api.map.baidu.com/location/ip';
const apiKey = 'xxx';

const getLocation = async ip => {
try {
const result = await request({url: apiUrl, params: {ak: apiKey, ip, coor: 'bd09ll'}, responseType: 'json'});
const {address_detail = {}, point = {}} = result.data?.content || {};
const {province, city, adcode} = address_detail;
const rectangle = point.x ? `${point.x},${point.y}` : undefined;
return {
province,
city,
adcode,
rectangle,
};
} catch (error) {
throw Error(error);
}
};

使用

const ipInfo = await getLocation(req.ip);


原文始发于微信公众号(前端道萌):node.js 几个功能插件使用总结

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/101887.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!