如何将S3存储桶中的PDF文件从一个Lambda发送到另一个Lambda
存在的错误
- 第一个错误:
Lambda.invoke()方法的Payload参数不支持直接传入Python字典,按照接口要求只能传入字节、字节数组或者类文件对象,直接传入dict会触发参数校验失败,就是你看到的报错。 - 第二个更核心的逻辑错误:你传的
/tmp/xxx.pdf是第一个Lambda运行环境本地的临时路径,两个Lambda的运行环境是完全隔离的,第二个Lambda根本无法访问第一个的本地文件,就算你把参数类型改对了,传路径过去也没用。
修复方案
推荐两种可行的实现方式,根据你的PDF大小选择:
方案1:直接传递PDF二进制内容(仅适合PDF大小不超过6MB的场景,Lambda同步调用Payload上限为6MB)
步骤:
- 将本地tmp路径下的PDF文件读取为二进制内容,再用base64编码为字符串(因为JSON无法直接传递二进制数据)
- 将参数序列化为JSON字符串,再转成UTF-8字节传入Payload
- 第二个Lambda收到Payload后,先解码base64得到PDF二进制内容即可使用
第一个Lambda修改后的调用代码:
import json import base64 import boto3 s3r = boto3.resource('s3') client = boto3.client('lambda') # 下载PDF到本地的代码保持不变 s3r.meta.client.download_file( Bucket='my_bucket', Key='pdf_folder' + '/{}'.format(pdf_name), Filename='/tmp/'+pdf_name ) # 读取PDF内容并base64编码 with open('/tmp/'+pdf_name, 'rb') as f: pdf_content = base64.b64encode(f.read()).decode('utf-8') # 构造Payload:先转JSON字符串再转字节 payload = json.dumps({ 'pdf_content': pdf_content, 'email': receiver_email, 'pdf_name': pdf_name }).encode('utf-8') client.invoke( FunctionName='second_lambda', InvocationType="RequestResponse", Payload=payload )
第二个Lambda的接收代码示例:
import base64 import json def lambda_handler(event, context): # event就是你传的Payload反序列化后的字典 pdf_content = base64.b64decode(event['pdf_content']) receiver_email = event['email'] pdf_name = event['pdf_name'] # 后续你可以把pdf_content存到本地tmp或者直接处理 with open(f'/tmp/{pdf_name}', 'wb') as f: f.write(pdf_content) # 其他业务逻辑
方案2:传递S3路径(推荐,无文件大小限制,性能更好)
不需要把PDF下载到第一个Lambda本地,直接把S3的桶名、文件Key以及邮箱传给第二个Lambda,第二个Lambda自己去S3下载文件即可,省去了多余的文件传输步骤,也不受Payload大小限制。
第一个Lambda代码简化为:
import json import boto3 client = boto3.client('lambda') payload = json.dumps({ 's3_bucket': 'my_bucket', 's3_key': f'pdf_folder/{pdf_name}', 'email': receiver_email }).encode('utf-8') client.invoke( FunctionName='second_lambda', InvocationType="RequestResponse", Payload=payload )
第二个Lambda的接收代码示例:
import boto3 import json s3 = boto3.client('s3') def lambda_handler(event, context): s3_bucket = event['s3_bucket'] s3_key = event['s3_key'] receiver_email = event['email'] # 自己从S3下载文件到本地tmp处理 pdf_name = s3_key.split('/')[-1] s3.download_file( Bucket=s3_bucket, Key=s3_key, Filename=f'/tmp/{pdf_name}' ) # 其他业务逻辑
内容的提问来源于stack exchange,提问作者some_programmer
相关产品推荐
相关产品推荐

