Koa框架常用中间件

parameter

参数校验工具

公共的rule

  • required:默认true,是否必须
  • type:类型,不同的类型有对应的rule
  • convertType:将输入参数转成特定的类型。支持intnumberstringboolean,也支持一个自定义转换方法的函数
  • default:默认值
  • widelyUndefined:覆盖全局的options.widelyUndefined

不同type独有的rule

类型 rule convertType 备注
int maxmin int 最大值和最小值;别名integer
number maxmin number 最大值和最小值
date string YYYY-MM-DD格式的数据
dateTime string YYYY-MM-DD HH:mm:ss格式的数据;别名datetime
id string /^\d+$/格式的数据
boolean boolean 布尔值;别名bool
string allowEmptyformatmaxmintrim string 字符串
email allowEmpty string 邮箱,验证规则RFC 5322
password comparemaxmin string min最小长度默认6
url string 验证规则web url
enum values 值必须是values中的一个
object rule 对象
array itemTyperulemaxmin 数组
// rules examples var rule = { name: 'string', age: {type: 'int', max: 200}, gender: ['male', 'female'], working: 'boolean', salary: {type: 'number', min: 0}, birthday: 'date', now: 'dateTime', id: 'id', childrens: { type: 'array', itemType: 'object', required: false, rule: { name: 'string', age: 'int', gender: ['male', 'female'], birthday: {type: 'date', required: false} } }, mate: { type: 'object', required: false, rule: { name: 'string', age: 'int', gender: ['male', 'female'], birthday: {type: 'date', required: false} } } }
  • 下载parameternpm i parameter --save

  • middleware/目录下添加parameter.js文件

const Parameter = require('parameter'); function parameter(translate) { return async (ctx, next) => { let parameter; if (typeof translate === 'function') { parameter = new Parameter({ translate, // convert: true }) } else { parameter = new Parameter() } ctx.verifyParams = function(rules, params) { if (!rules) { return; } if (!params) { params = ['GET', 'HEAD'].includes(this.method.toUpperCase()) ? this.request.query : this.request.body; // copy params = Object.assign({}, params, this.params); } const errors = parameter.validate(rules, params); if (!errors) { return; } const arrError = errors.map(error => error.field + ' ' + error.message) throw(new ctx.errs.ParameterException(arrError.join(';'))) } await next() } } module.exports = parameter
  • 修改app.js文件,配置中间件
const parameter = require('./middleware/parameter') app.use(parameter())
  • 在代码中使用
router.get('/test/parameter', async ctx => { const props = ctx.query ctx.verifyParams({ name: 'string', age: { type: 'int', convertType: 'int', max: 150, min: 0 } }, props) console.log(props) ctx.body = 'ddd' })

koa-json

koa读取和修改json

  • 下载koa-jsonnpm i koa-json --save

  • 修改app.js,配置

const json = require('koa-json') app.use(json())

koa-convert

对于比较老的使用Generate函数的koa中间件(< koa2),官方提供了一个灵活的工具可以将他们转为基于Promise的中间件供Koa2使用,同样也可以将新的基于Promise的中间件转为旧式的Generate中间件。

  • 下载koa-convertnpm i koa-convert --save

  • 使用示例

const convert = require('koa-convert') app.use(modernMiddleware) // yield → async/await app.use(convert(legacyMiddleware)) // compose app.use(convert.compose(legacyMiddleware, modernMiddleware)) function * legacyMiddleware (next) { // before yield next // after } function modernMiddleware (ctx, next) { // before return next().then(() => { // after }) }

koa-compress

当响应体比较大时,我们一般会启用类似Gzip的压缩技术减少传输内容,koa-compress提供了这样的功能,可根据需要进行灵活的配置。

  • 下载koa-compressnpm i koa-compress --save

  • 修改app.js,配置中间件

const compress = require('koa-compress') // app.use(compress({ // threshold: 2048 // })) app.use(compress({ // 只有在请求的content-type中有gzip类型,我们才会考虑压缩,因为zlib是压缩成gzip类型的 filter: function(content_type) { return /text/i.test(content_type); }, // 阀值,当数据超过1kb的时候,可以压缩 threshold: 1024, // zlib是node的压缩模 flush: require('zlib').Z_SYNC_FLUSH }))

koa-multer

koa-multer是一个node.js中间件,用于处理 multipart/form-data 类型的表单数据,它主要用于上传文件。它是写在 busboy 之上非常高效。

备注Multer 不会处理任何非 multipart/form-data 类型的表单数据,意思就是我们要上传图片必须在form表单上面加 multipart/form-data

  • 下载koa-multernpm i koa-multer --save

  • 引入配置koa-multer模块

const multer = require('koa-multer') // 配置 var storage = multer.diskStorage({ // 文件保存路径 destination: function (req, file, cb) { // 注意路径必须存在 cb(null, 'public/uploads/') }, //修改文件名称 filename: function (req, file, cb) { var fileFormat = (file.originalname).split(".") cb(null,Date.now() + "." + fileFormat[fileFormat.length - 1]) } }) // 加载配置 var upload = multer({ storage: storage })
  • 使用koa-multer
router.post('/doAdd', upload.single('face'), async (ctx, next) => { ctx.body = { filename: ctx.req.file.filename,//返回文件名 body:ctx.req.body } });
  • 不同图片上传到不同的地方
// router const uploadController = require('../controller/upload'); const router = require('koa-router')(); // 文件上传 const multer = require('koa-multer'); const settingUpload = (str) => { // 配置 -- 上传app logo let storage = multer.diskStorage({ // 文件保存路径 destination: function (req, file, cb) { cb(null, `static/uploads/${str}`) }, // 修改文件名称 filename: function (req, file, cb) { var fileFormat = (file.originalname).split("."); cb(null, Date.now() + "." + fileFormat[fileFormat.length - 1]); } }) // 加载配置 return multer({ storage: storage }); } // 路由 router.post('/avatar', settingUpload('avatar').single('file'), uploadController.avatarUpload) .post('/package', settingUpload('package').single('file'), uploadController.packageUpload); module.exports = router;
// controller const multer = require('koa-multer'); // 计算文件大小,将字节转为 KB 或者 MB const getSize = size => { size = size / 1024; if(size < 1024){ size = size.toFixed(2) + "KB" }else{ size = size / 1024 size = size.toFixed(2) + "MB" } return size } // 应用的logo上传 const avatarUpload = async (ctx, next) => { const host = ctx.request.origin; const src = ctx.req.file.path.slice(6).replace(/\\/g, "/"); ctx.success({ logo: host + src }) } // 安装包上传 const packageUpload = async (ctx, next) => { const host = ctx.request.origin; const src = ctx.req.file.path.slice(6).replace(/\\/g, "/"); ctx.success({ src: host + src, size: getSize(ctx.req.file.size) }) } module.exports = { avatarUpload, packageUpload }
  • 使用koa-multer上传多个图片
router.post('/doAdd', upload.fields([{ name: 'pic', maxCount: 1 }, { name: 'aaa', maxCount: 1 }]), async (ctx, next) => { console.log(ctx.req.files) })

node-uuid

在项目开发中我们常需要给某些数据定义一个唯一标识符,便于寻找,关联。

  • 下载node-uuidnpm i node-uuid --save

  • 在代码中使用

const uuid = require('node-uuid') // 基于时间戳生成 const id = uuid.v1() // 随机生成,一般不用这种形式。这种形式还是有一定几率重复的 const id = uuid.v4()

nodemailer

node中发送邮件

  • 下载nodemailernpm i nodemailer --save

  • 修改config/index.js文件,添加配置

const config = Object.assign({}, envConfig, { // ... email: { // 邮箱服务的主机,如smtp.qq.com host: 'smtp.163.com', port: 465, // 开启安全连接 // secure: true, // 用户信息 auth: { user: 'xxxx', // 邮箱 pass: 'xxxx' // 授权码,不是密码 } } })
  • utils/目录下添加email.js文件
const nodemailer = require("nodemailer") const emailConfig = require('../config').email /** * tolist 接收方的邮箱 //'li@latelee.org, latelee@163.com',//收件人邮箱,多个邮箱地址间用英文逗号隔开 * subject 邮件主题 标题 * cclist 抄送 //'li@latelee.org, latelee@163.com',//收件人邮箱,多个邮箱地址间用英文逗号隔开 * text 邮箱文本 * html 邮箱html格式的文本 * attachments 附件[{ * filename: 'img1.png', // 改成你的附件名 * path: 'public/images/img1.png', // 改成你的附件路径 * cid : '00000001' // cid可被邮件使用 * }] */ async function sendEmail(tolist, subject, cclist, text, html, attachments) { // 对465为 true,对其他端口为 false emailConfig.secure = (emailConfig.port == 465) // 使用默认的SMTP传输创建可重用的传输器对象 const transporter = nodemailer.createTransport(emailConfig) const mailOptions = { from: emailConfig.auth.user, // 谁发的 to: tolist, // 发给谁 subject: subject, // 主题 // text: 'this is an example by nodemailer', // 文本内容 // html: '', // html模板 // attachments: [ // 附件信息 // { // filename: '', // path: '' // } // ] } cclist && (mailOptions['cc'] = cclist) text && (mailOptions['text'] = text) html && (mailOptions['html'] = html) if(attachments && attachments!== isJSON(JSON.stringify(attachments))) { mailOptions['attachments'] = attachments } // 发送邮件 const res = await transporter.sendMail(mailOptions) return res } function isJSON(str) { if (typeof str == 'string') { try { const obj = JSON.parse(str) return (typeof obj == 'object' && obj ) } catch(e) { return false } } } module.exports = { sendEmail }
  • 在代码中使用
router.get('/test/email', async ctx => { const res = await sendEmail(/* ... */) ctx.success({ email: res }) })

备注:

  • 需要先设置邮箱,开启POP3/SMTP服务或者IMAP/SMTP服务
  • 开启之后会有一个授权码。填写到config/index.js文件的邮箱配置中

qr-image

生成图片二维码插件

  • 下载qr-imagenpm i qr-image --save

  • 代码中使用

const qr = require(qr-image) router.get('/test/qr', async ctx => { const url = 'http://www.wmm66.com/' // 生成的是可读的流数据 const img = qr.image(url) // 生成的是buffer,可以转成base64的字符串 // const img = qr.imageSync(url) // const baseimg = Buffer(img).toString('base64') ctx.type = 'image/png' ctx.body = img })

svg-captcha

图片验证码插件

  • 下载svg-captchanpm i svg-captcha --save

  • 在代码中使用

const svgCaptcha = require('svg-captcha') router.get('/test/captcha', async ctx => { const cap = svgCaptcha.create({ size: 4, // 随机长度 inverse: false, // 翻转颜色 fontSize: 36, // 字体大小 noise: 3, // 噪声线条数 width: 80, // 宽度 height: 30, // 高度 }) console.log(cap.text.toLowerCase()) ctx.type = 'image/svg+xml' ctx.body = cap.data })

调用 create() 之后,会返回一个对象,结构如下:{data: '', text:'' }

  • data:验证码 svg 图片
  • text:验证码字符

create()的参数如下

  • size: 4:验证码长度
  • ignoreChars: '0o1i':验证码字符中排除 0o1i
  • noise: 1:干扰线条的数量
  • inverse: false:翻转颜色
  • fontSize: 36:字体大小
  • color: true:验证码的字符是否有颜色,默认没有,如果设定了背景,则默认有
  • background: '#cc9966':验证码图片背景颜色
  • width: 80:宽度
  • height: 30:高度
  • createMathExpr(options)创建算术式验证码
const svgCaptcha = require('svg-captcha') router.get('/test/captcha', async ctx => { const cap = svgCaptcha.createMathExpr({}) console.log(cap.text.toLowerCase()) ctx.type = 'image/svg+xml' ctx.body = cap.data })

captchapng

图片验证码插件

  • 下载captchapngnpm i captchapng --save

  • 在代码中使用

const captchapng = require('captchapng') router.get('/test/captcha2', async ctx => { const cap = parseInt(Math.random() * 9000 + 1000) const p = new captchapng(80, 30, cap) p.color(0, 0, 0, 0) p.color(80, 80, 80, 255) const base64 = p.getBase64() ctx.success({ code: 'data:image/png;base64,' + base64, }) // 直接返回图片 // 把base64码转成buffer对象 // const dataBuffer = new Buffer(base64, 'base64') // ctx.type = 'image/png' // ctx.body = dataBuffer })

创作不易,若本文对你有帮助,欢迎打赏支持作者!

 分享给好友: