【问题标题】:How to parse multipart/form-data body with Koa?如何使用 Koa 解析 multipart/form-data 正文?
【发布时间】:2016-02-18 11:39:03
【问题描述】:

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

就我而言,造成混淆的原因是可用的替代方案的数量:

我想找到最简约/最接近express/koa/node的做事方式/哲学。

原来如此。以下。在接受的答案中。希望这会有所帮助。

【问题讨论】:

    标签: javascript koa body-parser


    【解决方案1】:

    您必须使用koa-multer,如官方Koa wiki中所述。

    所以一个简单的设置如下所示:

    const koa = require('koa');
    const multer = require('koa-multer');
    
    const app = koa();
    
    app.use(multer());
    
    app.use(function *() {
      this.body = this.req.body;
    });
    

    几点说明

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

    并将此 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>
    

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

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

    【讨论】:

    • 我实际上 asked why 解析的正文在 this.request 上不可用。
    • 请注意,当前维护的分支是 @koa/multer
    【解决方案2】:

    我经历了与您相同的调查,这里有其他方法可以使用 Koa 实现 multipart/form-data 正文解析。

    兼职工作人员

    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);
    })
    

    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);
    });
    

    在这两种情况下,您都会得到如下响应:

    {
      "topsecret": 1,
      "area51": {
        "lat": "37.235065",
        "lng": "-115.811117",
      }
    }
    

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

    另外,如果你为koa-body指定一个上传目录,它会为你保存上传的文件:

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

    【讨论】:

    • 使用function*(next)时如何使用async await?异步函数*(下一个)给出 404
    【解决方案3】:

    对于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';
      }
    }
    

    【讨论】:

    • 与自动字段一起使用。 var parts = await asyncBusboy(ctx.req, { autoFields: true // 将字段保存到parts.field(s) });
    【解决方案4】:

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

    1. koa-body,请注意它仅使用 multipart: true 选项解析 multipart/form-data
    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);
    
    1. koa-bodyparser,仅解析 multipart/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);
    
    1. @koa/multer,注意它仅在安装了multer 包时才解析multipart/form-data。另请注意,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);
    

    【讨论】:

      猜你喜欢
      • 2020-10-26
      • 2013-12-11
      • 1970-01-01
      • 2015-08-03
      • 1970-01-01
      • 1970-01-01
      • 2017-10-08
      • 2018-06-05
      • 2012-04-04
      相关资源
      最近更新 更多