拷贝Object
BOS Python SDK 支持通过 copy_object 拷贝已有 Object;对于大文件,还提供了分块拷贝(Multipart Upload Copy)模式。
运行以下示例前,请先参考初始化完成 BOS Client 初始化,并将示例中的 bucket_name、key 替换为实际值。
简单拷贝
1bos_client.copy_object(source_bucket_name, source_key, target_bucket_name, target_key)
BOS 的 CopyObject 接口以同步方式实现,服务端会等待拷贝实际完成后才返回成功,便于用户准确判断拷贝状态。
注意:
- 单次同步拷贝的对象大小不能超过 5GB,超过时服务端返回
EntityTooLarge错误,此时应改用分块拷贝。- 若源 Object 为归档(
ARCHIVE)类型,需先调用restore_object取回归档文件后才能拷贝。- 拷贝时若传入
user_metadata或content_type,SDK 会自动将拷贝指令设为replace(用新元信息覆盖);否则为copy。
拷贝时的条件判断
copy_object 可根据源 Object 的 ETag 或修改状态决定是否执行拷贝。其中 x-bce-copy-source-if-match 由独立的 etag 参数设置,其余三个条件 header 通过 copy_object_user_headers 传入:
| 名称 | 传入方式 | 说明 |
|---|---|---|
x-bce-copy-source-if-match |
etag 参数 |
源 Object 的 ETag 与所给值一致时才拷贝,否则失败。 |
x-bce-copy-source-if-none-match |
copy_object_user_headers |
源 Object 的 ETag 与所给值不一致时才拷贝,否则失败。 |
x-bce-copy-source-if-unmodified-since |
copy_object_user_headers |
源 Object 在指定时间之后未被修改时才拷贝,否则失败。 |
x-bce-copy-source-if-modified-since |
copy_object_user_headers |
源 Object 在指定时间之后被修改过时才拷贝,否则失败。 |
注意:
x-bce-copy-source-if-match必须通过etag参数传入。SDK 仅将x-bce-copy-source-if-none-match、x-bce-copy-source-if-unmodified-since、x-bce-copy-source-if-modified-since三个 header 列入copy_object_user_headers的白名单,若把x-bce-copy-source-if-match放进copy_object_user_headers,会被 SDK 静默丢弃而不生效。
1# 仅当源 Object 的 ETag 与所给值一致时才拷贝(if-match,通过 etag 参数)
2bos_client.copy_object(
3 source_bucket_name=bucket_name,
4 source_key=source_key,
5 target_bucket_name=bucket_name,
6 target_key=target_key,
7 etag="example-etag")
8
9# 其余条件通过 copy_object_user_headers 传入
10copy_object_user_headers = {
11 "x-bce-copy-source-if-none-match": "another-etag",
12 "x-bce-copy-source-if-unmodified-since": "Wed, 21 Jul 2020 07:23:48 GMT"
13}
14bos_client.copy_object(
15 source_bucket_name=bucket_name,
16 source_key=source_key,
17 target_bucket_name=bucket_name,
18 target_key=target_key,
19 copy_object_user_headers=copy_object_user_headers)
分块拷贝
对于超过 5GB 的大文件,或需要断点拷贝、网络较差的场景,可使用分块拷贝。分块拷贝包含 init、拷贝分块、complete 三步,其中 init 和 complete 与分块上传一致,拷贝分块使用 upload_part_copy:
1import os
2
3# 初始化分块上传,获取 upload_id
4upload_id = bos_client.initiate_multipart_upload(target_bucket, target_key).upload_id
5
6# 获取源 Object 大小
7left_size = int(bos_client.get_object_meta_data(source_bucket, source_key).metadata.content_length)
8offset = 0
9part_number = 1
10part_list = []
11
12while left_size > 0:
13 # 每块 5MB
14 part_size = 5 * 1024 * 1024
15 if left_size < part_size:
16 part_size = left_size
17
18 response = bos_client.upload_part_copy(
19 source_bucket, source_key, target_bucket, target_key,
20 upload_id, part_number, part_size, offset)
21
22 left_size -= part_size
23 offset += part_size
24 part_list.append({
25 "partNumber": part_number,
26 "eTag": response.etag
27 })
28 part_number += 1
29
30# 完成分块拷贝
31bos_client.complete_multipart_upload(target_bucket, target_key, upload_id, part_list)
注意:
offset以字节为单位,为分块的起始偏移位置;part_size为每个分块的大小。- 除最后一个分块外,其余每个分块的大小不得小于 100KB,否则完成分块拷贝时服务端返回
EntityTooSmall错误。- 若源 Object 为归档类型,需先取回归档文件。
恢复历史版本
对开启了版本控制的 Bucket,可将某个历史版本拷贝回同一 Bucket、同一 Key,从而生成一个内容等于该历史版本的新的当前版本:
1response = bos_client.copy_object(
2 source_bucket_name=bucket_name,
3 source_key=object_key,
4 target_bucket_name=bucket_name,
5 target_key=object_key,
6 source_version_id=history_version_id)
方法说明
| 方法 | 返回值 | 说明 |
|---|---|---|
bos_client.copy_object(source_bucket_name, source_key, target_bucket_name, target_key, ...) |
BceResponse |
拷贝 Object,单次最大 5GB。 |
bos_client.upload_part_copy(source_bucket, source_key, target_bucket, target_key, upload_id, part_number, part_size, offset, ...) |
BceResponse |
分块拷贝中拷贝单个分块。 |
评价此篇文章
