26

Amazon S3 REST API 文档说在 PUT 操作中上传的大小限制为 5gb。大于该大小的文件必须使用 multipart 上传。美好的。

但是,我本质上需要的是重命名可能比这更大的文件。据我所知,没有重命名或移动操作,因此我必须将文件复制到新位置并删除旧位置。大于 5gb 的文件究竟是如何完成的?我必须从存储桶到自身进行分段上传吗?在这种情况下,如何将文件分成几部分?

从阅读 boto 的源代码来看,对于大于 5gb 的文件,它似乎不会自动执行类似的操作。有没有我错过的内置支持?

4

4 回答 4

22

据我所知,没有重命名或移动操作,因此我必须将文件复制到新位置并删除旧位置。

没错,对于小于 5 GB 的对象/文件,通过PUT Object - Copy操作,然后是DELETE Object操作很容易做到(当然,这两者都在boto中受支持,请参阅copy_key()delete_key( ) ):

PUT 操作的这种实施会创建已存储在 Amazon S3 中的对象的副本。PUT 复制操作与执行 GET 然后执行 PUT 相同。添加请求标头 x-amz-copy-source 会使 PUT 操作将源对象复制到目标存储桶中。

但是,对于大于 5 GB 的对象/文件,这确实是不可能的:

注意
[...] 您可以使用此 API 在单个原子操作中创建最大 5 GB 的对象副本。但是,要复制大于 5 GB 的对象,您必须使用分段上传 API。有关概念信息 [...],请转到使用分段上传上传对象[...] [强调我的]

同时,Boto 也通过copy_part_from_key()方法支持这一点;不幸的是,在相应的拉取请求#425(允许多部分复制命令)之外没有记录所需的方法(虽然我自己还没有尝试过):

import boto
s3 = boto.connect_s3('access', 'secret')
b = s3.get_bucket('destination_bucket')
mp = b.initiate_multipart_upload('tmp/large-copy-test.mp4')
mp.copy_part_from_key('source_bucket', 'path/to/source/key', 1, 0, 999999999)
mp.copy_part_from_key('source_bucket', 'path/to/source/key', 2, 1000000000, 1999999999)
mp.copy_part_from_key('source_bucket', 'path/to/source/key', 3, 2000000000, 2999999999)
mp.copy_part_from_key('source_bucket', 'path/to/source/key', 4, 3000000000, 3999999999)
mp.copy_part_from_key('source_bucket', 'path/to/source/key', 5, 4000000000, 4999999999)
mp.copy_part_from_key('source_bucket', 'path/to/source/key', 6, 5000000000, 5500345712)
mp.complete_upload()

您可能想研究有关如何最终在 Java 或 .NET 中实现此目的的相应示例,这可能会提供对一般方法的更多见解,请参阅 使用 Multipart Upload API 复制对象

祝你好运!


附录

请注意以下关于一般复制的特殊性,很容易被忽视:

复制对象时,您可以保留大部分元数据(默认)或指定新元数据。但是,ACL 不会保留,并为发出请求的用户设置为私有。要覆盖默认 ACL 设置,请在生成复制请求时使用 x-amz-acl 标头指定新 ACL。有关更多信息,请参阅 Amazon S3 ACL。[强调我的]

于 2012-04-28T15:57:26.090 回答
10

上面非常接近工作,不幸的是应该结束mp.complete_upload() 而不是错字upload_complete()

我在这里添加了一个工作 boto s3 多部分复制脚本,基于 AWS Java 示例,并使用超过 5 GiB 的文件进行了测试:

https://gist.github.com/joshuadfranklin/5130355

于 2013-03-10T21:10:33.053 回答
2

我发现这种方法可以上传大于 5gigs 的文件,并将其修改为与 Boto 复制程序一起使用。这是原文:http ://boto.cloudhackers.com/en/latest/s3_tut.html

import math
from boto.s3.connection import S3Connection
from boto.exception import S3ResponseError


conn = S3Connection(host=[your_host], aws_access_key_id=[your_access_key],
                    aws_secret_access_key=[your_secret_access_key])

from_bucket = conn.get_bucket('your_from_bucket_name')
key = from_bucket.lookup('my_key_name')
dest_bucket = conn.get_bucket('your_to_bucket_name')

total_bytes = key.size
bytes_per_chunk = 500000000

chunks_count = int(math.ceil(total_bytes/float(bytes_per_chunk)))
file_upload = dest_bucket.initiate_multipart_upload(key.name)
for i in range(chunks_count):
    offset = i * bytes_per_chunk
    remaining_bytes = total_bytes - offset
    print(str(remaining_bytes))
    next_byte_chunk = min([bytes_per_chunk, remaining_bytes])
    part_number = i + 1
    file_upload.copy_part_from_key(dest_bucket.name, key.name, part_number,
                                   offset, offset + next_byte_chunk - 1)
file_upload.complete_upload()
于 2017-05-24T18:27:24.403 回答
1

现在的标准.copy方法将对大于 5gb 的文件执行分段上传。官方文档

import boto3
s3 = boto3.resource('s3')
copy_source = {
    'Bucket': 'mybucket',
    'Key': 'mykey'
}
s3.meta.client.copy(copy_source, 'otherbucket', 'otherkey')
于 2020-09-17T14:36:45.277 回答