使用Serverless处理multipart/form-data请求?

4

如何使用Serverless框架处理multipart/form-data数据?v.0.5.6

刚刚尝试了以下方法:

"requestTemplates": {
        "multipart/form-data": {
          "httpMethod": "$context.httpMethod",
          "body": "$input.json('$')",
          "queryParams": "$input.params().querystring",
          "headerParams": "$input.params().header",
          "headerParamNames": "$input.params().header.keySet()",
          "contentTypeValue": "$input.params().header.get('Content-Type')"
        },
        "application/json": {
          "httpMethod": "$context.httpMethod",
          "body": "$input.json('$')",
          "queryParams": "$input.params().querystring",
          "headerParams": "$input.params().header",
          "headerParamNames": "$input.params().header.keySet()",
          "contentTypeValue": "$input.params().header.get('Content-Type')"
        }
      }

action.js:

export function respond(event, cb) {

    var form = new formidable.IncomingForm();
    form.parse(event, function(err, fields, files) {
        if (err == null) {
            var response = {
                status: "true",
                data: fields,
                error: []
            };
            return cb(null, response);
        } else {
            console.log(err);
            return cb(null, ApiErrors.errors(402, err['message'] + fields));
        }
    });



}

但是出现了错误:errorMessage = "无法读取未定义的 'content-length' 属性";


如果 event 是普通的 Lambda 事件,那么表单已经被解析为您。从请求中解析输入是请求模板的一部分。因此,这个责任落在 API Gateway 上,而不是 Lambda。 - arjabbar
2个回答

9
我已经通过模拟 http.ClientRequest 并使用类似 formidable 的表单解析器工具,使 serverless 正常工作。
我正在使用 lambda-proxy 进行 API 网关事件配置。
const Stream      = require('stream').Readable;
const Formidable  = require('formidable');

module.exports.upload = ( e, ctx, cb ) => {
    let form = new Formidable.IncomingForm();

    let stream = new Stream();
    stream.push( e.body );
    stream.push( null );

    // NOTE: You'll likely want to toLowerCase() at least 'Content-Type' header key
    stream.headers = e.headers;

    form.parse( stream, (err, fields, files) => {
        // Work with your parsed form results here.
    });
}

1
这对我有用,但我还必须手动设置 e.headers ['content-length'] = e.body.length; ,否则将使用 dummyParser! - alexcasalboni

-2

嗯,我无法将其作为multipart/form-data格式,所以我使用了base64字符串。

action.js:

export function respond(event, cb) {
    //console.log('Received event:', JSON.stringify(event, null, 2));

    var key = new Date().toISOString().substr(0, 10) + '/' + String(Date.now());
    var contentType = event.body["data"].substr(0, event.body["data"].indexOf(';'));

    if (!contentType.match(/(\.|\/)(gif|jpe?g|png)$/i)) {
        return cb(null, 'invalid content type, gif, jpg, and png supported');
    }
    var data = new Buffer(event.body["data"].replace(/^image\/\w+;base64,/, ''),'base64');

    var params = {
        Bucket: 'your-bucket',
        Key: key,
        Body: data,
        ContentEncoding: 'base64',
        ContentType: contentType,
        ACL: 'public-read'
    };
    s3.upload(params, function (err, data) {
        if (err) {
            console.log(err);
            return cb(null, ApiErrors.errors(402, err['message']));
        } else {
            var response = {
                status: "true",
                data: {
                    url: urlPrefix + key
                },
                error: []
            };
            return cb(null, response);
        }
    });

}

请求模板:

"requestTemplates": {
        "application/json": {
          "httpMethod": "$context.httpMethod",
          "body": "$input.json('$')",
          "header": "$input.params().header.get($header)",
          "headerParam": "$input.params().header.keySet()",
          "contentType": "$input.params().header.get('Content-Type')"
        }
      },

1
@GurpreetSinghDrish,那个解决方案是针对serverless 0.5的。现在情况完全不同了。 - Marckaraujo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接