通过AWS Lambda与API Gateway上传PDF/docx至S3遇乱码问题求助
这个问题我之前处理过!核心原因是API Gateway默认会把二进制类型的请求体(比如PDF、docx)转成Base64编码,而你现在的代码直接读取了这个Base64字符串,既导致日志显示乱码,也把编码后的内容传到了S3,自然无法正常打开。普通文本文件因为本身是可打印字符,Base64编码后看起来还是正常文本,所以没暴露问题。
解决步骤
1. 配置API Gateway支持二进制媒体类型
首先得让API Gateway知道哪些类型的请求是二进制数据,确保它能正确处理转码:
- 打开AWS控制台的API Gateway服务,找到你的目标API
- 切换到「Settings」标签页,在「Binary Media Types」区域点击「Add binary media type」
- 可以添加具体的MIME类型,比如:
application/pdf(针对PDF文件)application/vnd.openxmlformats-officedocument.wordprocessingml.document(针对docx文件)- 或者直接加
*/*匹配所有类型(适合测试场景,生产环境建议指定具体类型)
- 重要提醒:配置完后必须点击API顶部的「Deploy API」,选择你的部署阶段(比如prod),否则配置不会生效!
2. 修改Lambda代码处理Base64编码的请求体
API Gateway会把二进制请求的Body转成Base64字符串,同时在请求事件里标记isBase64Encoded=true。你需要在代码里判断这个标记,解码后再上传到S3:
下面是适配你场景的Java代码示例(从你的日志代码来看,你用的是Java Lambda对吧?):
import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3ClientBuilder; import com.amazonaws.services.s3.model.PutObjectRequest; import java.io.ByteArrayInputStream; import java.util.Base64; public class S3UploadHandler { // 替换成你的目标S3桶名 private static final String S3_BUCKET = "your-target-bucket"; private final AmazonS3 s3Client = AmazonS3ClientBuilder.defaultClient(); public String handleRequest(APIGatewayProxyRequestEvent event, Context context) { try { // 从请求头提取文件名(Content-Disposition格式类似:form-data; name="file"; filename="test.pdf") String contentDisposition = event.getHeaders().getOrDefault("Content-Disposition", ""); String fileName = contentDisposition.split("filename=")[1].replaceAll("\"", ""); // 处理请求体:如果是Base64编码则解码,否则直接转字节 byte[] fileContent; if (event.isBase64Encoded()) { fileContent = Base64.getDecoder().decode(event.getBody()); } else { fileContent = event.getBody().getBytes(); } // 上传到S3 s3Client.putObject( new PutObjectRequest(S3_BUCKET, fileName, new ByteArrayInputStream(fileContent), null) ); context.getLogger().log("Successfully uploaded file: " + fileName + " (size: " + fileContent.length + " bytes)"); return String.format("File %s uploaded successfully", fileName); } catch (Exception e) { context.getLogger().log("Upload failed: " + e.getMessage()); return "Upload error: " + e.getMessage(); } } }
3. 关于日志乱码的说明
二进制文件(比如PDF)的原始字节本身就包含很多不可打印的ASCII字符,即使API Gateway不转Base64,直接打印这些字节也会显示乱码。所以日志里看到乱码是正常的,不用纠结——只要最终上传到S3的文件能正常打开,就说明处理正确。如果需要在日志里确认上传状态,打印文件名、文件大小这类元数据就足够了。
测试的时候,上传PDF后可以去S3控制台下载文件,打开看看是否正常。如果还是有问题,先检查API Gateway的部署是否生效,再确认Lambda代码里的Base64解码逻辑是否正确。
内容的提问来源于stack exchange,提问作者yuvanath
相关产品推荐
相关产品推荐

