AWS Lambda从S3下载文件至/tmp目录时出现数据丢失(文件大小异常)的问题求助
解决AWS Lambda下载S3大文件时大小异常的问题
看起来你遇到的问题是Lambda下载S3文件后大小严重缩水,从230MB变成了330KB,这大概率是下载过程被中断或者代码细节没处理到位。我帮你梳理几个常见原因和对应的解决方案:
一、先排查最容易忽略的问题
1. Lambda超时时间太短
默认情况下Lambda的超时时间只有3秒,下载230MB的文件完全不够,中途就会被强制终止,导致文件只下载了一部分。
- 解决方法:在Lambda控制台的函数配置里,把超时时间调整到60秒(甚至更长,根据你的网络情况)。
2. 确认/tmp目录空间(可能性较低,但可以验证)
Lambda现在默认给/tmp分配512MB空间,230MB是足够的,但可以在代码里加一行检查,排除空间不足的可能:
import shutil disk_usage = shutil.disk_usage('/tmp') print(f"/tmp可用空间: {disk_usage.free / (1024*1024):.2f} MB")
如果可用空间确实不足,可以在Lambda配置里调整/tmp的大小(最大支持10GB)。
3. 使用download_fileobj时未用二进制模式
如果你尝试过download_fileobj,一定要确保用wb模式打开文件——文本模式会损坏二进制文件(比如wav),直接导致大小异常:
with open(new_file_name, 'wb') as f: s3.download_fileobj(bucket_name, fileKey, f)
download_file方法内部已经处理了二进制模式,所以这个问题只针对download_fileobj。
二、添加调试和校验的修正代码
我给你修改了代码,加上了S3元数据校验、错误捕获和重试逻辑,方便你定位问题:
import os import boto3 import shutil def data_processor(event, context): print("EVENT:: ", event) bucket_name = 'asr-collection' fileKey = 'cc_continuous/testing/1645136763813.wav' path = '/tmp' output_path = os.path.join(path, 'mydir') # 检查/tmp可用空间 disk_usage = shutil.disk_usage('/tmp') print(f"/tmp可用空间: {disk_usage.free / (1024*1024):.2f} MB") if not os.path.exists(output_path): os.makedirs(output_path) s3 = boto3.client("s3") new_file_name = os.path.join(output_path, os.path.basename(fileKey)) # 先获取S3文件的真实大小,做对比基准 try: obj_meta = s3.head_object(Bucket=bucket_name, Key=fileKey) s3_file_size = obj_meta['ContentLength'] print(f"S3文件实际大小: {s3_file_size / (1024*1024):.2f} MB") except Exception as e: print(f"获取S3元数据失败: {str(e)}") return None try: # 下载文件 s3.download_file( Bucket=bucket_name, Key=fileKey, Filename=new_file_name ) local_size = os.path.getsize(new_file_name) print(f"本地文件大小: {local_size / (1024*1024):.2f} MB") # 校验大小,不匹配则重试一次 if local_size != s3_file_size: print("⚠️ 文件大小不匹配,尝试重新下载...") os.remove(new_file_name) s3.download_file(bucket_name, fileKey, new_file_name) local_size_retry = os.path.getsize(new_file_name) print(f"重试后大小: {local_size_retry / (1024*1024):.2f} MB") if local_size_retry == s3_file_size: print("✅ 重试成功,文件下载完整") else: print("❌ 重试后仍不匹配,需要进一步排查") else: print("✅ 文件下载完整") except Exception as e: print(f"下载过程出错: {str(e)}") return None return None
三、其他可能的排查方向
- VPC网络限制:如果你的Lambda部署在VPC里,需要确保VPC能访问S3——要么配置NAT网关,要么创建S3的VPC端点,否则下载会因为网络不通而中断。
- boto3版本过旧:旧版本的boto3可能存在大文件下载的bug,你可以在代码里打印版本号
print(boto3.__version__),如果版本低于1.20,建议升级到最新稳定版。 - S3版本控制:检查S3桶是否开启了版本控制,确认你下载的是最新版本的文件,而不是旧的小文件。
- 权限问题:虽然能下载部分文件,但如果权限有部分限制(比如只允许下载部分内容,这种情况比较少见),可以检查Lambda执行角色的权限,确保有
s3:GetObject的完整权限。
内容的提问来源于stack exchange,提问作者DD24
相关产品推荐
相关产品推荐

