如何用Koa解析multipart/form-data体?

eig*_*ive 18 javascript koa body-parser

因为我花了一些(太多)时间来弄清楚这个简单的要求.我在这里记录了multipart/form-data使用Koa 实现体解析的方法.

就我而言,混淆的原因是那里有可供选择的替代品:

我想找到最简约/最接近的express/koa/node做法/做事哲学.

所以这就是.下面.在接受的答案.希望这可以帮助.

eig*_*ive 13

你必须使用官方Koa维基中所述的koa-multer.

所以一个简单的设置看起来像:

const koa = require('koa');
const multer = require('koa-multer');

const app = koa();

app.use(multer());

app.use(function *() {
  this.body = this.req.body;
});
Run Code Online (Sandbox Code Playgroud)

几个笔记:

  • Multer只会解析类型请求的主体 multipart/form-data
  • 请注意使用this.req.body而不是Koa的增压this.request(不确定这是否是故意的,但这确实令人困惑......我希望解析body后可用this.request...)

并将此HTML表单发送为FormData:

<form>
  <input type="hidden" name="topsecret" value="1">
  <input type="text" name="area51[lat]" value="37.235065">
  <input type="text" name="area51[lng]" value="-115.811117">
  ...
</form>
Run Code Online (Sandbox Code Playgroud)

可以让您按预期访问嵌套属性:

// -> console.log(this.req.body)
{
  "topsecret": 1,
  "area51": {
    "lat": "37.235065",
    "lng": "-115.811117",
  }
}
Run Code Online (Sandbox Code Playgroud)


sil*_*min 12

对于Koa2,您可以使用async- busboy,因为其他解决方案不支持promisesasync/await.

来自文档的示例:

import asyncBusboy from 'async-busboy';

// Koa 2 middleware
async function(ctx, next) {
  const {files, fields} = await asyncBusboy(ctx.req);

  // Make some validation on the fields before upload to S3
  if ( checkFiles(fields) ) {
    files.map(uploadFilesToS3)
  } else {
    return 'error';
  }
}
Run Code Online (Sandbox Code Playgroud)


ns1*_*s16 10

我有三个适合我的解决方案:

  1. koa-body,请注意它multipart/form-data仅解析multipart: true选项。
const Koa = require('koa');
const koaBody = require('koa-body');
const Router = require('koa-router');

const app = new Koa();
const router = new Router();

app.use(koaBody({ multipart: true }));

router.post('/', async ctx => {
    const body = ctx.request.body;
    // some code...
});

app.use(router.routes());

app.listen(3000);
Run Code Online (Sandbox Code Playgroud)
  1. koa-bodyparsermultipart/form-data只解析koa2-formidable它之前的中间件。
const Koa = require('koa');
const bodyParser = require('koa-bodyparser');
const formidable = require('koa2-formidable');
const Router = require('koa-router');

const app = new Koa();
const router = new Router();

app.use(formidable());
app.use(bodyParser());

router.post('/', async ctx => {
    const body = ctx.request.body;
    // some code...
});

app.use(router.routes());

app.listen(3000);
Run Code Online (Sandbox Code Playgroud)
  1. @koa/multer,请注意它multipart/form-data仅在安装multer包时解析。另请注意,koa-multer已弃用,请勿使用它。
const Koa = require('koa');
const Router = require('koa-router');
const multer = require('@koa/multer');

const app = new Koa();
const router = new Router();
const upload = multer(); // you can pass options here

app.use(upload.any());

router.post('/', async ctx => {
    const body = ctx.request.body;
    // some code...
});

app.use(router.routes());

app.listen(3000);
Run Code Online (Sandbox Code Playgroud)


sat*_*nas 5

我和您进行了相同的调查,这是multipart/form-data通过Koa 进行正文解析的其他方法。

合作男孩

var koa = require('koa');
var parse = require('co-busboy');

const app = koa();

app.use(function* (next) {
  // the body isn't multipart, so busboy can't parse it 
  if (!this.request.is('multipart/*')) return yield next;

  var parts = parse(this),
      part,
      fields = {};
  while (part = yield parts) {
    if (part.length) {
      // arrays are busboy fields 
      console.log('key: ' + part[0]);
      console.log('value: ' + part[1]);

      fields[part[0]] = part[1];
    } else {
      // it's a stream, you can do something like:
      // part.pipe(fs.createWriteStream('some file.txt'));
    }
  }

  this.body = JSON.stringify(fields, null, 2);
})
Run Code Online (Sandbox Code Playgroud)

koa-body

var koa = require('koa');
var router = require('koa-router');
var koaBody = require('koa-body')({ multipart: true });

const app = koa();

app.use(router(app));

app.post('/', koaBody, function *(next) {
  console.log(this.request.body.fields);

  this.body = JSON.stringify(this.request.body, null, 2);
});
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,您都会收到类似以下的响应:

{
  "topsecret": 1,
  "area51": {
    "lat": "37.235065",
    "lng": "-115.811117",
  }
}
Run Code Online (Sandbox Code Playgroud)

但就我个人而言,我更喜欢koa-body的工作方式。另外,与koa-validate等其他中间件兼容。

另外,如果您将上传目录指定为koa-body,它将为您保存上传的文件:

var koaBody = require('koa-body')({
  multipart: true,
  formidable: { uploadDir: path.join(__dirname, 'tmp') }
});
Run Code Online (Sandbox Code Playgroud)