Boto3 中的 IOError download_file
IOError in Boto3 download_file
背景
我正在使用以下 Boto3 代码从 S3 下载文件。
for record in event['Records']:
bucket = record['s3']['bucket']['name']
key = record['s3']['object']['key']
print (key)
if key.find('/') < 0 :
if len(key) > 4 and key[-5:].lower() == '.json': //File is uploaded outside any folder
download_path = '/tmp/{}{}'.format(uuid.uuid4(), key)
else:
download_path = '/tmp/{}/{}'.format(uuid.uuid4(), key)//File is uploaded inside a folder
如果在 S3 存储桶中上传新文件,将触发此代码,并通过此代码下载新上传的文件。
当上传到任何文件夹之外时,此代码工作正常。
但是,当我在目录中上传文件时,发生 IO 错误。
这是我遇到的 IO 错误的转储。
[Errno 2] No such file or directory:
/tmp/316bbe85-fa21-463b-b965-9c12b0327f5d/test1/customer1.json.586ea9b8:
IOError
test1
是我的 S3 存储桶中上传 customer1.json
的目录。
查询
关于如何解决这个错误有什么想法吗?
出现错误是因为您试图将文件下载并保存到不存在的目录中。使用os.mkdir之前下载文件创建目录。
# ...
else:
item_uuid = str(uuid.uuid4())
os.mkdir('/tmp/{}'.format(item_uuid))
download_path = '/tmp/{}/{}'.format(item_uuid, key) # File is uploaded inside a folder
注意:使用系统路径操作时最好使用os.path.join()。所以上面的代码可以重写为:
# ...
else:
item_uuid = str(uuid.uuid4())
os.mkdir(os.path.join(['tmp', item_uuid]))
download_path = os.path.join(['tmp', item_uuid, key]))
也可能会引发错误,因为您在 s3 存储桶文件的下载路径中包含“/tmp/”,但不包含 tmp
文件夹,因为它可能在 s3 上不存在。使用这些文章确保您走在正确的道路上:
感谢 Andriy Ivaneyko 的帮助,我找到了使用 boto3 的解决方案。
使用下面的代码我能够完成我的任务。
for record in event['Records']:
bucket = record['s3']['bucket']['name']
key = record['s3']['object']['key']
fn='/tmp/xyz'
fp=open(fn,'w')
response = s3_client.get_object(Bucket=bucket,Key=key)
contents = response['Body'].read()
fp.write(contents)
fp.close()
我遇到了同样的问题,错误消息引起了很多混乱,(文件名后的随机字符串扩展名)。在我的例子中,它是由丢失的目录路径引起的,该路径不存在。
您的代码的问题在于 download_path 是错误的。每当您尝试下载 s3 存储桶中目录下的任何文件时,下载路径将变为:
download_path = /tmp/<uuid><object key name>
where <object key name> = "<directory name>/<object name>"
这使得下载路径为:
download_path = /tmp/<uuid><directory name>/<object key name>
代码将失败,因为不存在具有 uuid 目录名称的目录。您的代码只允许下载 /tmp 目录下的文件。
要解决此问题,考虑在创建下载路径时拆分您的密钥,您也可以避免检查文件上传到存储桶中的位置。这只会在下载路径中获取目标文件名。例如:
for record in event['Records']:
bucket = record['s3']['bucket']['name']
key = record['s3']['object']['key']
print (key)
download_path = '/tmp/{}{}'.format(uuid.uuid4(), key.split('/')[-1])
背景
我正在使用以下 Boto3 代码从 S3 下载文件。
for record in event['Records']:
bucket = record['s3']['bucket']['name']
key = record['s3']['object']['key']
print (key)
if key.find('/') < 0 :
if len(key) > 4 and key[-5:].lower() == '.json': //File is uploaded outside any folder
download_path = '/tmp/{}{}'.format(uuid.uuid4(), key)
else:
download_path = '/tmp/{}/{}'.format(uuid.uuid4(), key)//File is uploaded inside a folder
如果在 S3 存储桶中上传新文件,将触发此代码,并通过此代码下载新上传的文件。
当上传到任何文件夹之外时,此代码工作正常。
但是,当我在目录中上传文件时,发生 IO 错误。 这是我遇到的 IO 错误的转储。
[Errno 2] No such file or directory: /tmp/316bbe85-fa21-463b-b965-9c12b0327f5d/test1/customer1.json.586ea9b8: IOError
test1
是我的 S3 存储桶中上传 customer1.json
的目录。
查询
关于如何解决这个错误有什么想法吗?
出现错误是因为您试图将文件下载并保存到不存在的目录中。使用os.mkdir之前下载文件创建目录。
# ...
else:
item_uuid = str(uuid.uuid4())
os.mkdir('/tmp/{}'.format(item_uuid))
download_path = '/tmp/{}/{}'.format(item_uuid, key) # File is uploaded inside a folder
注意:使用系统路径操作时最好使用os.path.join()。所以上面的代码可以重写为:
# ...
else:
item_uuid = str(uuid.uuid4())
os.mkdir(os.path.join(['tmp', item_uuid]))
download_path = os.path.join(['tmp', item_uuid, key]))
也可能会引发错误,因为您在 s3 存储桶文件的下载路径中包含“/tmp/”,但不包含 tmp
文件夹,因为它可能在 s3 上不存在。使用这些文章确保您走在正确的道路上:
感谢 Andriy Ivaneyko 的帮助,我找到了使用 boto3 的解决方案。
使用下面的代码我能够完成我的任务。
for record in event['Records']:
bucket = record['s3']['bucket']['name']
key = record['s3']['object']['key']
fn='/tmp/xyz'
fp=open(fn,'w')
response = s3_client.get_object(Bucket=bucket,Key=key)
contents = response['Body'].read()
fp.write(contents)
fp.close()
我遇到了同样的问题,错误消息引起了很多混乱,(文件名后的随机字符串扩展名)。在我的例子中,它是由丢失的目录路径引起的,该路径不存在。
您的代码的问题在于 download_path 是错误的。每当您尝试下载 s3 存储桶中目录下的任何文件时,下载路径将变为:
download_path = /tmp/<uuid><object key name>
where <object key name> = "<directory name>/<object name>"
这使得下载路径为:
download_path = /tmp/<uuid><directory name>/<object key name>
代码将失败,因为不存在具有 uuid 目录名称的目录。您的代码只允许下载 /tmp 目录下的文件。
要解决此问题,考虑在创建下载路径时拆分您的密钥,您也可以避免检查文件上传到存储桶中的位置。这只会在下载路径中获取目标文件名。例如:
for record in event['Records']:
bucket = record['s3']['bucket']['name']
key = record['s3']['object']['key']
print (key)
download_path = '/tmp/{}{}'.format(uuid.uuid4(), key.split('/')[-1])