赞
踩
你可以使用 boto3
Python库来进行S3文件的读取和下载。下面是一个基本的示例代码:
import boto3
# 配置S3连接
s3 = boto3.resource('s3')
bucket_name = 'your-bucket-name'
# 定义要下载的文件名
file_key = 'your-file-path-in-s3'
# 下载文件
s3.Bucket(bucket_name).download_file(file_key, 'local-file-path')
这段代码首先通过boto3
连接到S3并选择要读取的存储桶,然后定义要下载的文件路径和本地文件路径,并使用Bucket
对象上的download_file
方法实现下载。
注意需要安装boto3
库,可以使用以下命令进行安装:
pip install boto3
如果要读取和下载的文件较大,你可以使用Range
参数实现分块下载。下面是一个示例代码:
import boto3 # 配置S3连接 s3 = boto3.client('s3') bucket_name = 'your-bucket-name' # 定义要下载的文件名 file_key = 'your-file-path-in-s3' # 定义每次下载的块大小和起始位置,并生成本地文件名 chunk_size = 1024 * 1024 # 1 MB start_byte = 0 local_file_path = 'local-file-path' while True: # 使用range参数获取要下载的字节范围 end_byte = start_byte + chunk_size - 1 range_str = f"bytes={start_byte}-{end_byte}" # 下载块并将其追加到本地文件 resp = s3.get_object(Bucket=bucket_name, Key=file_key, Range=range_str) to_write = resp['Body'].read() if len(to_write) == 0: break with open(local_file_path, 'ab') as f: f.write(to_write) # 更新起始位置以准备下一块的下载 start_byte += chunk_size
这段代码使用了boto3
的client
对象,通过设置range
参数,将文件分块下载,并逐块写入本地文件,因为默认下载工具只会一次加载整个文件从而造成大量内存的占用,降低程序效率和稳定性。
如果你遇到了如下错误:
An error occurred (InvalidArgument) when calling the GetObject operation: Requests specifying a byte-range must include an If-Range header.
这是因为使用了Range
参数后,必须同时指定一个If-Range
头信息,指定下载起始位置。你可以使用以下代码添加If-Range
头信息:
import boto3 # 配置S3连接 s3 = boto3.client('s3') bucket_name = 'your-bucket-name' # 定义要下载的文件名 file_key = 'your-file-path-in-s3' local_file_path = 'local-file-path' # 获取文件大小,作为设置`If-Range`头信息的依据 file_size = s3.head_object(Bucket=bucket_name, Key=file_key)['ContentLength'] # 定义每次下载的块大小,分块下载并追加到本地文件 chunk_size = 1024 * 1024 # 1 MB start_byte = 0 while True: end_byte = start_byte + chunk_size - 1 range_str = f'bytes={start_byte}-{end_byte}/{file_size}' resp = s3.get_object(Bucket=bucket_name, Key=file_key, Range=range_str, IfRange=file_size) to_write = resp['Body'].read() if len(to_write) == 0: break with open(local_file_path, 'ab') as f: f.write(to_write) start_byte += chunk_size
这里我使用了head_object
来获取文件大小,然后将其作为If-Range
头信息的值。
如果你遇到了 botocore.exceptions.ConnectionClosedError
错误,这通常意味着某些网络问题,或者AWS端点问题,导致连接未能从AWS端点接收到有效的响应,再次请求可能解决问题。
尝试重新运行你的代码或等待一段时间再尝试使用相同的 AWS 凭证登录,看看这些步骤是否能够解决问题。 如果问题仍然存在,你可以尝试以下解决方案:
config
参数传递给 boto3.client()
来增加连接超时或重试次数。例如:import boto3
from botocore.config import Config
s3 = boto3.client('s3', config=Config(connect_timeout=10, retries={'max_attempts': 5}))
这里将连接超时设置为10秒,并最大重试次数设置为5次。你可以根据需要调整这些参数。
如果你仍然遇到 botocore.exceptions.ConnectionClosedError
错误,可以尝试进一步调试网络问题。
在你的代码中添加以下代码打印出调试信息:
import boto3 import botocore from botocore.config import Config # 定义S3连接配置并开启调试模式 s3_config = Config(connect_timeout=10, retries={'max_attempts': 5}, debug={'http': {'response': True, 'http2': True}}) # 创建S3客户端并使用连接配置 s3_client = boto3.client('s3', config=s3_config) try: # 尝试访问S3对象 response = s3_client.get_object(Bucket='my-bucket', Key='mykey') print(response) except botocore.exceptions.ClientError as e: print(f"Got an error: {e.response['Error']['Code']}") print(f"Debug info: {e.response['ResponseMetadata']['HTTPHeaders']}")
以上代码中,我们使用 botocore.config.Config
开启了调试模式,并尝试访问 S3 对象。如果访问过程中出现错误,代码将会输出调试信息,从而帮助你进一步检查和解决问题。
当你运行上述代码并遇到 ConnectionClosedError
错误时,检查调试输出信息是否包含类似以下内容:
DEBUG - Response headers: {'x-amz-request-id': '...', 'x-amz-id-2': '...', 'content-type': 'application/xml', 'transfer-encoding': 'chunked', 'date': '...', 'server': 'AmazonS3'}, response payload: '<?xml version="1.0" encoding="UTF... (truncated)'
这个输出表示 AWS S3 返回了 XML 格式的错误信息。尝试在 S3 控制台中查找错误代码,或者按错误输出信息提示进一步解决问题。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。