如何让XMLHTTPRequest+FormData避免multipart/form-data或在Lambda中解析该格式
解决方案:两种方式解决Lambda表单提交解析问题
方式一:让XMLHTTPRequest+FormData以application/x-www-form-urlencoded格式提交
你当前代码里手动设置了Content-Type头,但直接发送FormData对象时,浏览器会忽略这个设置,自动采用multipart/form-data格式。要解决这个问题,需要把FormData转换成urlencoded格式的字符串:
修改后的JavaScript代码:
const form = document.querySelector('#my-form-id') form.addEventListener('submit', event => { event.preventDefault() const xhr = new XMLHttpRequest() xhr.open('POST', 'www.myurl.com/submit') // 将FormData转为urlencoded格式字符串 const data = new FormData(form) const encodedData = new URLSearchParams(data).toString() // 设置正确的请求头 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded') xhr.send(encodedData) xhr.onload = () => { console.log(xhr.responseText) } })
核心逻辑是用URLSearchParams把FormData对象转成与纯HTML表单提交一致的urlencoded格式字符串,这样请求体就会被Lambda正常解析。
方式二:在AWS Lambda Python环境中解析multipart/form-data
如果不想修改前端代码,可以在Lambda端直接处理multipart格式的请求体,以下是两种实现方式:
1. 使用Python内置cgi模块(无需额外依赖)
import cgi from io import BytesIO def lambda_handler(event, context): # 获取请求体和Content-Type头 body = event['body'] content_type = event['headers'].get('Content-Type', '') # 构造CGI环境变量,用于解析表单 environ = { 'CONTENT_TYPE': content_type, 'CONTENT_LENGTH': str(len(body)), 'REQUEST_METHOD': 'POST' } # 将请求体转为文件对象 fp = BytesIO(body.encode('utf-8')) # 解析multipart表单数据 form = cgi.FieldStorage(fp=fp, environ=environ, keep_blank_values=True) # 获取表单字段值 name = form.getvalue('name') email = form.getvalue('email') # 后续业务逻辑 return { 'statusCode': 200, 'body': f"收到数据:姓名={name},邮箱={email}" }
2. 使用第三方python-multipart库(需打包依赖)
如果需要更简洁的代码,可以使用python-multipart库,使用前需要将该库打包到Lambda部署包,或通过Lambda层引入:
from multipart import parse_form_data from io import BytesIO def lambda_handler(event, context): body = event['body'] content_type = event['headers'].get('Content-Type', '') # 解析multipart数据 environ = {'CONTENT_TYPE': content_type} fp = BytesIO(body.encode('utf-8')) form, _ = parse_form_data(environ, fp) # 获取表单字段 name = form.get('name') email = form.get('email') return { 'statusCode': 200, 'body': f"收到数据:姓名={name},邮箱={email}" }
内容的提问来源于stack exchange,提问作者Eyal Redler
相关产品推荐
相关产品推荐

