如何使用Python和boto3从URL流式传输大文件至AWS S3?
解决流式传输URL文件到AWS S3时生成0字节文件的问题
你的代码出现0字节文件的核心原因是没有开启requests的流式下载模式,默认情况下requests.get()会把整个文件加载到内存,但后续读取response.raw时可能已经没有剩余内容,导致上传空数据。另外,过小的multipart_threshold参数也可能干扰正常传输逻辑。
修正后的代码
import requests import boto3 from boto3.s3.transfer import TransferConfig # 目标文件URL link = "https://www.stats.govt.nz/assets/Uploads/Annual-enterprise-survey/Annual-enterprise-survey-2021-financial-year-provisional/Download-data/annual-enterprise-survey-2021-financial-year-provisional-csv.csv" # 初始化requests会话并开启流式下载 session = requests.Session() response = session.get(link, stream=True) # 强制检查请求是否成功,避免处理错误响应 response.raise_for_status() # S3配置 s3_bucket = "my-bucket-name" s3_file_path = "file-path-to-my-file/data1.csv" s3 = boto3.client('s3') # 确保解码内容(处理gzip压缩等情况) response.raw.decode_content = True # 配置分片传输:阈值设为100MB(适合大文件),并发数按需调整 transfer_config = TransferConfig( multipart_threshold=100 * 1024 * 1024, max_concurrency=4, use_threads=True ) # 流式上传到S3 s3.upload_fileobj(response.raw, s3_bucket, s3_file_path, Config=transfer_config)
关键要点说明
stream=True:这是流式传输的核心,开启后requests不会一次性下载整个文件到内存,而是按需读取,完美适配大文件场景,同时避免内存溢出。response.raise_for_status():强制校验HTTP请求状态,一旦返回4xx/5xx错误会直接抛出异常,避免上传空的错误响应内容。- 合理设置
TransferConfig:multipart_threshold建议设为100MB-1GB(根据文件大小调整),过小的阈值会导致不必要的分片,反而影响传输效率;use_threads=True开启多线程上传,提升大文件传输速度。
额外优化建议
- 如果目标URL支持断点续传,可以添加
Range请求头实现分块下载+上传,进一步提升稳定性。 - 给boto3客户端配置重试策略,应对网络波动导致的传输中断:
from botocore.config import Config s3 = boto3.client( 's3', config=Config( retries={ 'max_attempts': 5, 'mode': 'standard' } ) )
内容的提问来源于stack exchange,提问作者ai_lab_developer
相关产品推荐
相关产品推荐

