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

Node.js+XLSX实现XLSX转JSON:浏览器上传数据乱码求助

问题排查与解决方案

核心问题分析

浏览器上传后乱码、CloudWatch日志显示form-data头混入数据区,而Postman测试正常,本质是浏览器端上传的multipart/form-data请求未被正确解析,导致Lambda收到的不是纯文件二进制内容,而是包含表单边界、字段头的完整表单数据。Postman会自动处理multipart/form-data的边界和编码,因此能正常触发流程。


分步排查与修复

1. 前端上传代码问题(最常见)

如果前端手动设置了Content-Type: multipart/form-data,会导致浏览器无法自动添加表单边界参数,API Gateway无法识别并解析多部分数据。

错误示例:

const formData = new FormData();
formData.append('file', fileInput.files[0]);

fetch(apiGatewayUrl, {
  method: 'POST',
  headers: {
    'Content-Type': 'multipart/form-data' // 手动设置会导致边界丢失
  },
  body: formData
});

修复:

移除手动设置的Content-Type,让浏览器自动生成带边界的请求头:

const formData = new FormData();
formData.append('file', fileInput.files[0]);

fetch(apiGatewayUrl, {
  method: 'POST',
  body: formData // 浏览器会自动添加正确的Content-Type及边界
});

2. API Gateway配置问题

即使开启了二进制媒体类型,若映射模板未正确解析multipart/form-data,仍会把完整表单数据传给Lambda。

配置步骤:

  1. 添加二进制媒体类型:在API Gateway控制台的「设置」中,添加multipart/form-data到二进制媒体类型列表。
  2. 配置集成请求映射模板:
    • 进入对应API的集成请求页面,选择「映射模板」,添加multipart/form-data类型的模板。
    • 使用以下模板提取文件内容和文件名(示例为JSON格式):
      {
        "file_content": "$util.base64Encode($util.parseMultiPartForm($input.body).file[0].content)",
        "filename": "$util.parseMultiPartForm($input.body).file[0].filename"
      }
      
    该模板会自动解析表单数据,将文件内容编码为Base64后传递给Lambda。

3. Lambda函数处理问题

若Lambda直接将event.body当作文件内容读取,而未解析multipart/form-data或解码Base64,会导致乱码。

Python Lambda示例(处理映射模板传递的数据):

import base64
import io
import pandas as pd

def lambda_handler(event, context):
    # 解码Base64格式的文件内容
    file_content = base64.b64decode(event['file_content'])
    # 读取XLSX文件
    df = pd.read_excel(io.BytesIO(file_content))
    # 转换为JSON并上传S3等后续逻辑...
    return {"statusCode": 200, "body": "处理完成"}

Node.js Lambda示例(手动解析multipart数据,若未配置映射模板):

使用busboy库解析完整表单数据:

const Busboy = require('busboy');
const XLSX = require('xlsx');

exports.handler = async (event) => {
    return new Promise((resolve, reject) => {
        const busboy = new Busboy({
            headers: {
                'content-type': event.headers['Content-Type'] || event.headers['content-type']
            }
        });

        let fileBuffer = Buffer.from('');

        busboy.on('file', (_, file) => {
            file.on('data', (chunk) => {
                fileBuffer = Buffer.concat([fileBuffer, chunk]);
            });
            file.on('end', () => {
                // 读取XLSX文件
                const workbook = XLSX.read(fileBuffer, { type: 'buffer' });
                // 后续JSON转换、上传S3逻辑...
                resolve({ statusCode: 200, body: '处理完成' });
            });
        });

        busboy.on('error', (err) => reject(err));
        busboy.write(Buffer.from(event.body, event.isBase64Encoded ? 'base64' : 'utf8'));
        busboy.end();
    });
};

验证方法

  1. 查看CloudWatch日志中的event结构:若event.body包含------WebKitFormBoundary等边界字符串,说明API Gateway未解析表单数据,需检查映射模板或前端请求头。
  2. 测试前端上传后的请求头:通过浏览器开发者工具确认Content-Type包含boundary=xxx参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 18:40:06