Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

KoaJS how to get files from multipart form data?

Tags:

forms

node.js

koa

When I post a multipart form,

<form name="acount_manage"  action="/update" enctype="multipart/form-data" method="post">
    <input type="file" name="file">
</form>

It throws:

Error: Unsupported content-type: multipart/form-data
at Object.<anonymous> (e:\...\node_modules\co-body\lib\any.js:51:15)

any.js:

/**
 * Module dependencies.
 */

var json = require('./json');
var form = require('./form');
var text = require('./text');

var JSON_CONTENT_TYPES = [
  'application/json',
  'application/json-patch+json',
  'application/vnd.api+json',
  'application/csp-report',
  'application/ld+json'

];

/**
 * Return a a thunk which parses form and json requests
 * depending on the Content-Type.
 *
 * Pass a node request or an object with `.req`,
 * such as a koa Context.
 *
 * @param {Request} req
 * @param {Options} [opts]
 * @return {Function}
 * @api public
 */

module.exports = function(req, opts){
  req = req.req || req;

  // parse Content-Type
  var type = req.headers['content-type'] || '';
  type = type.split(';')[0];

  // json
  if (~JSON_CONTENT_TYPES.indexOf(type)) return json(req, opts);

  // form
  if ('application/x-www-form-urlencoded' == type) return form(req, opts);

  // text
  if ('text/plain' == type) return text(req, opts);

  // invalid
  return function(done){
    var message = type ? 'Unsupported content-type: ' + type : 'Missing content-type';
    var err = new Error(message);
    err.status = 415;
    done(err);
  };
};

then,I changed the code

if ('application/x-www-form-urlencoded' == type) return form(req, opts);

to

if ('application/x-www-form-urlencoded' == type || 'multipart/form-data'==type) return form(req, opts);

no error ,but I can't get the request'data :

debug(this.request.files.file);

Result is undefined.

I am using KoaJs.

like image 333
lichao123125 Avatar asked Jul 27 '15 10:07

lichao123125


2 Answers

For koa 2, try async-busboy to parse request body as co-busboy doesn't play well with promise based async.

Example from the docs:

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';
  }
}
like image 86
silkAdmin Avatar answered Nov 14 '22 10:11

silkAdmin


Try koa-body library.

Example:

Put this middleware BEFORE the route middleware:

app.use(require('koa-body')({
    formidable:{
        uploadDir: __dirname + '/public/uploads', // directory where files will be uploaded
        keepExtensions: true // keep file extension on upload
    },
    multipart: true,
    urlencoded: true,
}));

Then use in route middleware

async function(ctx, next) {
    ctx.request.body.files.file  // file is the input name
}

This code is for KoaJs 2, but this library works with KoaJs 1 too.

like image 44
Valera Avatar answered Nov 14 '22 10:11

Valera