Parse multipart/form-data from body as string on AWS Lambda

后端 未结 4 1798
梦毁少年i
梦毁少年i 2020-12-14 17:55

I\'m glad to see AWS now supports multipart/form-data on AWS Lambda, but now that the raw data is in my lambda function how do I process it?

I see multiparty is a g

相关标签:
4条回答
  • 2020-12-14 18:18

    Building on @AvnerSo :s answer, here's a simpler version of a function that gets the request body and headers as parameters and returns a promise of an object containing the form fields and values (skipping files):

    const parseForm = (body, headers) => new Promise((resolve, reject) => {
      const contentType = headers['Content-Type'] || headers['content-type'];
      const bb = new busboy({ headers: { 'content-type': contentType }});
    
      var data = {};
    
      bb.on('field', (fieldname, val) => {
        data[fieldname] = val;
      }).on('finish', () => {
        resolve(data);
      }).on('error', err => {
        reject(err);
      });
    
      bb.end(body);
    });
    
    0 讨论(0)
  • 2020-12-14 18:21

    If you want to get a ready to use object, here is the function I use. It returns a promise of it and handle errors:

    import Busboy from 'busboy';
    import YError from 'yerror';
    import getRawBody from 'raw-body';
    
    const getBody = (content, headers) =>
        new Promise((resolve, reject) => {
          const filePromises = [];
          const data = {};
          const parser = new Busboy({
            headers,
            },
          });
    
          parser.on('field', (name, value) => {
            data[name] = value;
          });
          parser.on('file', (name, file, filename, encoding, mimetype) => {
            data[name] = {
              filename,
              encoding,
              mimetype,
            };
            filePromises.push(
              getRawBody(file).then(rawFile => (data[name].content = rawFile))
            );
          });
          parser.on('error', err => reject(YError.wrap(err)));
          parser.on('finish', () =>
            resolve(Promise.all(filePromises).then(() => data))
          );
          parser.write(content);
          parser.end();
        })
    
    0 讨论(0)
  • 2020-12-14 18:24

    This worked for me - using busboy

    credits owed to Parse multipart/form-data from Buffer in Node.js which I copied most of this from.

    const busboy = require('busboy');
    
    const headers = {
      'Content-Type': 'application/json',
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'OPTIONS, POST',
      'Access-Control-Allow-Headers': 'Content-Type'
    };
    
    function handler(event, context) {
      var contentType = event.headers['Content-Type'] || event.headers['content-type'];
      var bb = new busboy({ headers: { 'content-type': contentType }});
    
      bb.on('file', function (fieldname, file, filename, encoding, mimetype) {
        console.log('File [%s]: filename=%j; encoding=%j; mimetype=%j', fieldname, filename, encoding, mimetype);
    
        file
        .on('data', data => console.log('File [%s] got %d bytes', fieldname, data.length))
        .on('end', () => console.log('File [%s] Finished', fieldname));
      })
      .on('field', (fieldname, val) =>console.log('Field [%s]: value: %j', fieldname, val))
      .on('finish', () => {
        console.log('Done parsing form!');
        context.succeed({ statusCode: 200, body: 'all done', headers });
      })
      .on('error', err => {
        console.log('failed', err);
        context.fail({ statusCode: 500, body: err, headers });
      });
    
      bb.end(event.body);
    }
    
    module.exports = { handler };
    
    0 讨论(0)
  • 2020-12-14 18:34

    busboy doesn't work for me in the "file" case. It didn't throw an exception so I couldn't handle exception in lambda at all.

    I'm using aws-lambda-multipart-parser lib wasn't hard like so. It just parses data from event.body and returns data as Buffer or text.

    Usage:

    const multipart = require('aws-lambda-multipart-parser');
    
    const result = multipart.parse(event, spotText) // spotText === true response file will be Buffer and spotText === false: String
    

    Response data:

    {
        "file": {
            "type": "file",
            "filename": "lorem.txt",
            "contentType": "text/plain",
            "content": {
                "type": "Buffer",
                "data": [ ... byte array ... ]
            } or String
        },
        "field": "value"
    }
    
    0 讨论(0)
提交回复
热议问题