使用Boto从AWS Glacier下载大型存档文件

6
我正在尝试使用Python包Boto从Glacier下载一个大的存档文件(约1TB)。我目前使用的方法如下:
import os
import boto.glacier
import boto
import time

ACCESS_KEY_ID = 'XXXXX'
SECRET_ACCESS_KEY = 'XXXXX'
VAULT_NAME = 'XXXXX'
ARCHIVE_ID = 'XXXXX'
OUTPUT = 'XXXXX'

layer2 = boto.connect_glacier(aws_access_key_id = ACCESS_KEY_ID,
                              aws_secret_access_key = SECRET_ACCESS_KEY)

gv = layer2.get_vault(VAULT_NAME)

job = gv.retrieve_archive(ARCHIVE_ID)
job_id = job.id

while not job.completed:
    time.sleep(10)
    job = gv.get_job(job_id)

if job.completed:
    print "Downloading archive"
    job.download_to_file(OUTPUT)

问题是作业ID在24小时后过期,这不足以恢复整个归档。我需要将下载分成至少4个部分。我该如何做,并将输出写入单个文件中?


你的下载时间超过了24小时吗?我的意思是,你受到带宽限制了吗?在EC2上,将其提取/重新发送到S3,以便稍后下载,或将其拉到EC2盒子中并从那里下载。 - tedder42
2个回答

4
看起来你可以在调用job.download_to_file时简单地指定chunk_size参数,就像这样:
if job.completed:
    print "Downloading archive"
    job.download_to_file(OUTPUT, chunk_size=1024*1024)

然而,如果您无法在24小时内下载所有块,则不能使用layer2选择仅下载您错过的块。

第一种方法

使用layer1,您可以简单地使用方法get_job_output并指定要下载的字节范围。

代码如下:

file_size = check_file_size(OUTPUT)

if job.completed:
    print "Downloading archive"
    with open(OUTPUT, 'wb') as output_file:
        i = 0
        while True:
            response = gv.get_job_output(VAULT_NAME, job_id, (file_size + 1024 * 1024 * i, file_size + 1024 * 1024 * (i + 1)))
            output_file.write(response)
            if len(response) < 1024 * 1024:
                break
            i += 1

使用这个脚本,当脚本失败时,您应该可以重新运行脚本并继续下载您离开的归档。
第二种方法
通过挖掘boto代码,我发现Job类中有一个“私有”方法,您也可以使用:_download_byte_range。使用此方法仍然可以使用layer2。
file_size = check_file_size(OUTPUT)

if job.completed:
    print "Downloading archive"
    with open(OUTPUT, 'wb') as output_file:
        i = 0
        while True:
            response = job._download_byte_range(file_size + 1024 * 1024 * i, file_size + 1024 * 1024 * (i + 1)))
            output_file.write(response)
            if len(response) < 1024 * 1024:
                break
            i += 1

我最终使用了第二种方法,在进行一些微调后效果很好。我添加了一个条件语句,如果文件大小不等于0,则将写入方法设置为“ab”。这样,如果重新运行输出,它就会被追加而不是覆盖。此外,字节范围元组的第二个元素需要减1。最后,我添加了重试异常和哈希验证,就像_download_to_fileob源代码中所示。 - sahoang

-1

您需要在boto.connect_glacier函数中添加region_name参数,如下所示:

    layer2 = boto.connect_glacier(aws_access_key_id = ACCESS_KEY_ID,
                                aws_secret_access_key = SECRET_ACCESS_KEY,
                                region_name = 'your region name')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接