You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Ruby中解析curl提交的form-data?AWS Lambda场景

解决AWS Lambda解析multipart/form-data的问题

遇到Lambda里没法直接解析form-data请求的情况确实挺烦的,毕竟默认情况下Lambda不会自动帮你把原始的form-data内容转换成结构化的对象。下面给你两个实用的方案,不用依赖Rack也能轻松实现event['body']['index_name']这种便捷的取值方式:

方案一:Python环境用multipart库

这是Python生态里处理multipart数据比较成熟的库,步骤如下:

  1. 安装依赖并打包
    先在本地安装multipart库,然后把它和你的Lambda代码一起打包上传(或者用Lambda层管理依赖):

    pip install multipart -t ./lambda-code
    
  2. Lambda代码示例

    import base64
    import multipart
    
    def lambda_handler(event, context):
        # 处理base64编码的请求体(API Gateway代理集成默认会把二进制数据转成base64)
        if event.get('isBase64Encoded', False):
            body = base64.b64decode(event['body'])
        else:
            body = event['body'].encode('utf-8')
        
        # 从请求头里获取Content-Type(包含multipart的boundary信息)
        content_type = event['headers'].get('Content-Type', '')
        
        # 解析multipart数据
        parser = multipart.MultipartParser(body, content_type)
        form_data = {}
        uploaded_files = {}
    
        for part in parser.parts():
            if part.filename:
                # 处理上传的文件
                uploaded_files[part.name] = {
                    'filename': part.filename,
                    'content': part.raw.decode('utf-8'),  # 如果是二进制文件可以保留raw
                    'content_type': part.headers.get('Content-Type', '')
                }
            else:
                # 处理普通表单字段
                form_data[part.name] = part.value.decode('utf-8')
        
        # 现在就能像你想要的那样取值了!
        print(f"index_name的值:{form_data['index_name']}")
        print(f"上传的JSON文件内容:{uploaded_files['document']['content']}")
    
        return {
            'statusCode': 200,
            'body': f"成功接收index_name: {form_data['index_name']}"
        }
    

方案二:Node.js环境用busboy库

如果你的Lambda是用Node.js写的,busboy是处理multipart数据的常用工具:

  1. 安装依赖并打包
    同样先安装依赖:

    npm install busboy --save
    

    然后把node_modules和代码一起打包上传。

  2. Lambda代码示例

    const busboy = require('busboy');
    
    exports.handler = async (event) => {
        return new Promise((resolve, reject) => {
            // 初始化busboy,传入请求头信息
            const bb = busboy({ 
                headers: event.headers,
                limits: { fileSize: 10 * 1024 * 1024 } // 限制文件大小为10MB,根据需求调整
            });
    
            const formData = {};
            const uploadedFiles = {};
    
            // 监听普通字段
            bb.on('field', (fieldName, value) => {
                formData[fieldName] = value;
            });
    
            // 监听文件上传
            bb.on('file', (fieldName, fileStream, fileInfo) => {
                const { filename, mimeType } = fileInfo;
                const fileChunks = [];
    
                fileStream.on('data', (chunk) => fileChunks.push(chunk));
                fileStream.on('end', () => {
                    // 把文件块拼接成完整内容,这里以UTF-8编码为例(JSON文件适用)
                    const fileContent = Buffer.concat(fileChunks).toString('utf-8');
                    uploadedFiles[fieldName] = {
                        filename,
                        mimeType,
                        content: fileContent
                    };
                });
            });
    
            // 解析完成后的逻辑
            bb.on('finish', () => {
                console.log(`index_name的值:${formData.index_name}`);
                console.log(`上传的JSON文件内容:${uploadedFiles.document.content}`);
    
                resolve({
                    statusCode: 200,
                    body: JSON.stringify({
                        index_name: formData.index_name,
                        document: uploadedFiles.document
                    })
                });
            });
    
            // 处理错误
            bb.on('error', (err) => {
                console.error('解析失败:', err);
                reject({ statusCode: 500, body: '解析请求失败' });
            });
    
            // 把请求体传给busboy处理,注意base64解码
            const bodyBuffer = event.isBase64Encoded 
                ? Buffer.from(event.body, 'base64') 
                : Buffer.from(event.body);
            bb.end(bodyBuffer);
        });
    };
    

一些注意事项

  • API Gateway配置:如果用的是代理集成,要确保API Gateway没有对请求体做额外的格式化处理,让Lambda接收原始的请求数据。
  • 大小限制:API Gateway的请求体最大支持10MB,Lambda的内存和超时时间也要根据你处理的文件大小适当调整,避免超时。
  • 手动解析不推荐:虽然可以手动根据boundary分割原始body来解析,但容易出错(比如处理编码、文件二进制内容等),不如用成熟的第三方库省心。

内容的提问来源于stack exchange,提问作者ngw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:33:16