【问题标题】:Parse multipart/form-data from body as string on AWS Lambda在 AWS Lambda 上将正文中的 multipart/form-data 解析为字符串
【发布时间】:2016-11-30 15:24:11
【问题描述】:

我很高兴see AWS 现在支持 AWS Lambda 上的 multipart/form-data,但是现在原始数据在我的 lambda 函数中,我该如何处理它?

我看到multiparty 是 Node 中用于多部分处理的一个很好的多部分库,但它的构造函数需要一个请求,而不是原始字符串。

我在 Lambda 函数上收到的输入消息(在应用正文映射模板之后)是:

{ "rawBody": "--ce0741b2-93d4-4865-a7d6-20ca51fe2689\r\nContent-Disposition: form-data; name=\"Content-Type\"\r\n\r\nmultipart/mixed; boundary=\"------------020601070403020003080006\"\r\n--ce0741b2-93d4-4865-a7d6-20ca51fe2689\r\nContent-Disposition: form-data; name=\"Date\"\r\n\r\nFri, 26 Apr 2013 11:50:29 -0700\r\n--ce0741b2-93d4-4865-a7d6-20ca51fe2689\r\nContent-Disposition: form-data; name=\"From\"\r\n\r\nBob <bob@mg.mydomain.io>\r\n--ce0741b2-93d4-4865-a7d6-20ca51fe2689\r\nContent-Disposition: form-data; name=\"In-Reply-To\"\r... 

等和一些文件数据。

我使用的身体映射模板是

{
  "rawBody" : "$util.escapeJavaScript($input.body).replaceAll("\\'", "'")"
}

如何解析这些数据以访问发布到我的 Lambda 函数的字段和文件?

【问题讨论】:

    标签: node.js amazon-web-services aws-lambda


    【解决方案1】:

    busboy 在“文件”案例中对我不起作用。它没有抛出异常,所以我根本无法在 lambda 中处理异常。

    我使用aws-lambda-multipart-parser lib 并不难。它只是从 event.body 中解析数据并将数据作为 Buffer 或文本返回。

    用法:

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

    响应数据:

    {
        "file": {
            "type": "file",
            "filename": "lorem.txt",
            "contentType": "text/plain",
            "content": {
                "type": "Buffer",
                "data": [ ... byte array ... ]
            } or String
        },
        "field": "value"
    }
    

    【讨论】:

    • 我尝试了 multiparty 并且正要尝试 busboy(看起来他们正在做同样的事情)但找到了你的回复和 aws-lambda-multipart-parser 拯救了我的一天,谢谢
    • 这也拯救了我的一天。赏金开始就是为了这个答案 - 希望它会在此过程中得到一些额外的支持。
    • 我得到一个空的回复:{}。你们有没有遇到同样的问题?
    • 如果有人收到回复:{},试试这个:if (event.isBase64Encoded) { event.body = Buffer.from(event.body, 'base64').toString(); } let result = multipart.parse(event, true);
    • "该项目目前已关闭,不会进行进一步更新。请考虑使用其他库。" - 有人知道是否有更稳定的支持吗?如果 AWS 在他们的 SDK 中添加支持会很好。
    【解决方案2】:

    这对我有用 - 使用 busboy

    感谢Parse multipart/form-data from Buffer in Node.js,我大部分都是从那里复制过来的。

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

    【讨论】:

      【解决方案3】:

      在@AvnerSo :s 答案的基础上,这是一个更简单的函数版本,它获取请求正文和标头作为参数并返回包含表单字段和值(跳过文件)的对象的承诺:

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

      【讨论】:

        【解决方案4】:

        如果你想得到一个可以使用的对象,这里是我使用的函数。它返回一个承诺并处理错误:

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

        【讨论】:

          猜你喜欢
          • 2017-10-08
          • 2018-07-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-12-11
          • 2016-02-18
          • 1970-01-01
          • 2020-05-18
          相关资源
          最近更新 更多