本文介绍如何在受版本控制的存储空间(Bucket)中上传文件(Object)。

简单上传

在已开启版本控制的Bucket中,OSS会为新添加的Object自动生成唯一的版本ID,并在响应header中通过x-oss-version-id形式返回。在暂停了版本控制的Bucket中,新添加的Object的版本ID为“null”,上传同名Object,后一次会覆盖前一次上传的文件内容。OSS保证同一个Object只会有一个版本的ID为“null”。

以下代码用于简单上传:
# -*- coding: utf-8 -*-
import oss2

# 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
# Endpoint以杭州为例,其它Region请按实际情况填写。
bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>')

# 上传文件。
result = bucket.put_object('<yourObjectName>', 'content of object')
# HTTP返回码。
print('http response code: {0}'.format(result.status))
# 查看本次上传object的版本id。
print('put object version:', result.versionid)

简单上传的详细信息请参见PutObject

追加上传

在受版本控制的Bucket中,仅支持对于当前版本为Appendable类型的Object执行追加(AppendObject)操作,不支持对于历史版本为Appendable类型的Object执行AppendObject操作。
说明
  • 对当前版本为Appendable类型的Object执行AppendObject操作时,OSS不会为该Appendable类型的Object生成历史版本。
  • 对当前版本为Appendable类型的Object执行PutObject或DeleteObject操作时,OSS会将该Appendable类型的Object保留为历史版本,且该Object不允许继续追加。
  • 不支持对当前版本为非Appendable类型的Object(包括 Normal Object、Delete Marker等)执行AppendObject 操作。
  • 目标Bucket在开启或暂停版本控制状态下,不支持对Appendable类型Object执行拷贝操作。
以下代码用于追加上传:
# -*- coding: utf-8 -*-
import oss2

# 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
# Endpoint以杭州为例,其它Region请按实际情况填写。
bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>')

# 设置首次上传的追加位置(Position参数)为0。
result = bucket.append_object('<yourObjectName>', 0, 'content of first append')
# 查看本次执行追加文件的object的版本id
print('append object versionid:', result.versionid)
# 如果不是首次上传,可以通过bucket.head_object方法或上次追加返回值的next_position属性,得到追加位置。
bucket.append_object('<yourObjectName>', result.next_position, 'content of second append')

追加上传的详细信息请参见AppendObject

分片上传

在受版本控制的Bucket中,调用CompleteMultipartUpload接口来完成整个文件的分片上传,OSS会为整个文件生成唯一的版本ID,并在响应header中以x-oss-version-id的形式返回。

以下代码用于分片上传:
# -*- coding: utf-8 -*-
import os
import oss2
from oss2 import SizedFileAdapter, determine_part_size
from oss2.models import PartInfo

# 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
# Endpoint以杭州为例,其它Region请按实际情况填写。
bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>')

key = '<yourObjectName>'
filename = '<yourLocalFile>'

total_size = os.path.getsize(filename)
# determine_part_size方法用来确定分片大小。
part_size = determine_part_size(total_size, preferred_size=100 * 1024)

# 初始化分片。
upload_id = bucket.init_multipart_upload(key).upload_id
parts = []

# 逐个上传分片。
with open(filename, 'rb') as fileobj:
    part_number = 1
    offset = 0
    while offset < total_size:
        num_to_upload = min(part_size, total_size - offset)
    # SizedFileAdapter(fileobj, size)方法会生成一个新的文件对象,重新计算起始追加位置。
        result = bucket.upload_part(key, upload_id, part_number,
                                    SizedFileAdapter(fileobj, num_to_upload))
        parts.append(PartInfo(part_number, result.etag))

        offset += num_to_upload
        part_number += 1

# 完成分片上传。
result = bucket.complete_multipart_upload(key, upload_id, parts)
# 查看response中携带的上传文件的versionid
print('result.versionid:', result.versionid)


# 验证分片上传。
with open(filename, 'rb') as fileobj:
    assert bucket.get_object(key).read() == fileobj.read()

分片上传的详细信息请参见CompleteMultipartUpload