参数解析
动态路由参数
import Koa from 'koa'
import Router from '@koa/router'
const app = new Koa()
// 不传路由前缀,默认就是根路由 /
const router = new Router()
// 请求路径为 /Klaus/20
router.get('/:name/:age', (ctx) => {
// 属性值都是字符串类型值
console.log(ctx.params) // { name: 'Klaus', age: '20' }
ctx.body = `Hello ${ctx.params.name}, you are ${ctx.params.age} years old`
})
app.use(router.routes()).use(router.allowedMethods())
app.listen(3000)
查询字符串
import Koa from 'koa'
import Router from '@koa/router'
const app = new Koa()
// 不传路由前缀,默认就是根路由 /
const router = new Router()
// 请求路径为 /user?name=Tom&age=23
router.get('/user', (ctx) => {
console.log(ctx.query) // { name: 'Tom', age: '23' }
ctx.body = `Hello ${ctx.query.name}, you are ${ctx.query.age} years old`
})
app.use(router.routes()).use(router.allowedMethods())
app.listen(3000)
JSON格式和urlencode参数
import Koa from 'koa'
import Router from '@koa/router'
import bodyParser from 'koa-bodyparser'
const app = new Koa()
// 挂载bodyParser中间件
// 1. 可以自动解析请求体中的JSON对象和urlencoded数据
// 2. 将结果挂载到 ctx.request.body 上
app.use(bodyParser())
const router = new Router({ prefix: '/user' })
// 传入的 json数据为 {"name": "Tom", "age": 30}
router.post('/json', (ctx) => {
console.log(ctx.request.body) // { name: 'Tom', age: 30 }
ctx.body = ctx.request.body
})
// 传入的 urlencoded数据为 name=Tom&age=30
router.post('/urlencoded', (ctx) => {
// 会自动转对象,但属性值为字符串 => url是字符串值,无法确定你要的是数字还是值以为数值的字符串
console.log(ctx.request.body) // { name: 'Tom', age: '30' }
ctx.body = ctx.request.body
})
app.use(router.routes()).use(router.allowedMethods())
app.listen(3000)
POST请求的FormData格式
解析 FormData 格式数据需要通过 multer
Koa基于multer进行了二次封装,提供了中间件@koa/multer
@koa/multer会自动将将表单数据解析出来并自动挂载到ctx.request.body中
和
koa-router一样,早期叫koa-multer,已经停止维护,推荐用@koa/multer。
pnpm install @koa/multer multer
import Koa from 'koa'
import Router from '@koa/router'
// 本质基于 multer 实现,使用方式和 multer 一样
import multer from '@koa/multer'
const app = new Koa()
const router = new Router({ prefix: '/user' })
// 表单数据并不是所有接口都需要解析的,所以一般作用于单个接口
// 和 express 一样,路径中间件的类型为 router.<method>(path, ...middlewares)
// 对应中间件会被加入数组中,并被依次执行
router.post('/form', multer().any(), (ctx) => {
console.log(ctx.request.body)
ctx.body = ctx.request.body
})
app.use(router.routes()).use(router.allowedMethods())
app.listen(3000)
文件上传
import Koa from 'koa'
import Router from '@koa/router'
import path from 'node:path'
// 底层基于 multer 实现,使用方式和 multer 一样
// 可以用于解析表单数据,也可以用于解析文件上传
import multer from '@koa/multer'
const app = new Koa()
const router = new Router({ prefix: '/user' })
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads')
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname))
}
})
const upload = multer({ storage: storage })
router.post('/upload', upload.single('avatar'), (ctx) => {
// 凡是 ctx.request 和 ctx.response 上存在的属性 都可以通过 ctx 进行访问
// 包括 multer 解析后挂载的文件信息 => 这是 @koa/multer 额外进行实现的
// 单个文件信息挂载到 ctx.file 上,多个文件信息挂载到 ctx.files 上
// 但有一个特别的: ctx.body 是 ctx.response.body
// 而请求体的body 只能通过ctx.request.body 来获取
console.log(ctx.file)
ctx.body = '上传成功'
})
app.use(router.routes()).use(router.allowedMethods())
app.listen(3000, () => {
console.log('Server is running on port 3000')
})
数据响应
返回文本内容
import Koa from 'koa'
const app = new Koa()
app.use(ctx => {
// 返回文本数据 并设置响应头为 text/plain
ctx.body = 'Hello World'
// 可以通过 ctx.set 来设置响应头
// ctx.set('Content-Type', 'text/plain')
})
app.listen(3000)
返回二进制
import Koa from 'koa'
const app = new Koa()
app.use(ctx => {
// 返回文本数据 并设置响应头为 application/octet-stream
ctx.body = Buffer.from('Hello World')
})
app.listen(3000)
返回数据流
import Koa from 'koa'
import fs from 'fs'
const app = new Koa()
app.use(ctx => {
const stream = fs.createReadStream('./uploads/avatar-1750581078613.jpeg')
// 设置响应头
// 不设置,默认当做 application/octet-stream 来处理, 此时客户端会自动按照 8位一个字节来处理
// 设置为 image/jpeg 后,Content-Type 会自动设置为 image/jpeg
// 此时客户端会按照 image/jpeg 来处理,并最终显示为图片
// koa 通过 ctx.set(key, value) 来设置响应头
// 而 Content-Type 比较特殊,存在简写方式 ctx.type
// ctx.type = 'image/jpeg' 实际等价于 ctx.set('Content-Type', 'image/jpeg')
ctx.type = 'image/jpeg'
// 设置响应体
ctx.body = stream
})
app.listen(3000)
返回JSON
import Koa from 'koa'
const app = new Koa()
app.use(ctx => {
ctx.body = {
name: '张三',
age: 20,
gender: '男',
email: 'zhangsan@example.com',
phone: '12345678901',
address: '北京市海淀区'
}
})
app.listen(3000)
什么都不返回
import Koa from 'koa'
const app = new Koa()
app.use(ctx => {
// 没有任何响应头,koas会自动设置状态码为 204 No Content
// 默认情况下,有内容返回 200,无内容返回 204
ctx.body = null
})
app.listen(3000)
手动设置状态码
import Koa from 'koa'
const app = new Koa()
app.use(ctx => {
// 设置状态码 为 201 Created
ctx.status = 201
// 设置响应体
ctx.body = 'Hello World'
})
app.listen(3000)