使用 koa-body 接受 post 请求以及文件

koa

Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石。 通过利用 async 函数,Koa 帮你丢弃回调函数,并有力地增强错误处理。 Koa 并没有捆绑任何中间件, 而是提供了一套优雅的方法,帮助您快速而愉快地编写服务端应用程序。

koa-body

koa本身不能解析 post 的 body,因此需要添加中间件解析.
koa-bodyparser可以解析 post 的 body,但是无法处理上传的文件.这里我们使用 koa-body,它可以处理上传的文件和 post 请求,同时可以搭配 koa-router使用,在需要的地方添加配置.

可以处理的请求

  • multipart/form-data
  • application/x-www-urlencoded
  • application/json
  • application/json-patch+json
  • application/vnd.api+json
  • application/csp-report

使用(搭配 koa-router)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//处理 post 请求body 中的值
const Koa = require('koa');
const app = new Koa();
const router = require('koa-router')();
const koaBody = require('koa-body');
router.post('/users', koaBody(),
(ctx) => {
console.log(ctx.request.body);
// => POST body
ctx.body = JSON.stringify(ctx.request.body);
}
);
app.use(router.routes());
app.listen(3000);
1
2
3
4
5
6
7
8
9
//处理上传的文件
const routers = router.post(
"/",
koaBody({
multipart: true,
formidable: { maxFileSize: 1024*1000*100000 }
}),
uploadController.uploadVideo
);

主要参数

WX20190829-112657@2x
formidable 的相关配置参数
屏幕快照 2019-08-29 上午11.28.05

获取上传信息

文件

使用ctx.request.files来获取文件.因为默认开启多个文件上传,因此 ctx.request.files 是一个对象.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
async uploadVideo(ctx) {
const file = ctx.request.files.file;
const reader = fs.createReadStream(file.path);
const ext = file.name.split(".").pop();
const dir = path.join(__dirname, `../upload/${utils.getDirName()}`);
utils.checkDirExist(dir);
let fileName = `${utils.getDirName()}_${~~(Math.random() * 10000)}.${ext}`;
const fileLocation = `${dir}/${fileName}`;
const upStream = fs.createWriteStream(fileLocation);
reader.pipe(upStream);
await utils.transferFile(fileLocation, `/yunjia/${fileName}`);
ctx.body = {
code: 200,
url: `http://10.20.21.24:8080/${fileName}`
};
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//utils.js中的 transferFile 函数用来上传文件到指定的 ftp 服务器,
//同时确保返回前端 url 之前,上传已经完成
//因此使用了 koa 框架支持的 async 函数, await transferFile()
//确保文件上传完成以后,返回给前端文件的 url.
transferFile(fileLocation, path) {
return new Promise((resolve, reject) => {
let ftpClient = new FtpClient();
ftpClient.on("ready", function() {
ftpClient.put(fileLocation, path, err => {
if (err) {
reject(err);
}
console.dir("成功上传文件到服务器");
resolve();
ftpClient.end();
fs.unlinkSync(fileLocation);
});
});
ftpClient.connect(ftpConnectionConfig.ftpConnectionConfig);
});
}

获取 body 的值

使用ctx.request.body来获取.

thank u !