文档

Python上传文件

更新时间:

本文介绍如何在受版本控制的存储空间(Bucket)中使用简单上传、追加上传或者分片上传的方式来上传文件(Object)。

注意事项

  • 本文以华东1(杭州)外网Endpoint为例。如果您希望通过与OSS同地域的其他阿里云产品访问OSS,请使用内网Endpoint。关于OSS支持的Region与Endpoint的对应关系,请参见访问域名和数据中心

  • 本文以从环境变量读取访问凭证为例。如何配置访问凭证,请参见配置访问凭证

  • 本文以OSS域名新建OSSClient为例。如果您希望通过自定义域名、STS等方式新建OSSClient,请参见初始化

  • 要上传文件,您必须有oss:PutObject权限。具体操作,请参见为RAM用户授权自定义的权限策略

简单上传

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

以下代码用于简单上传:

# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
# 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
# 填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
# yourBucketName填写存储空间名称。
bucket = oss2.Bucket(auth, 'https://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)

追加上传

在受版本控制的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操作。

以下代码用于追加上传:

# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
# 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
# 填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
# yourBucketName填写存储空间名称。
bucket = oss2.Bucket(auth, 'https://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')

分片上传

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

以下代码用于分片上传:

# -*- coding: utf-8 -*-
import os
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
from oss2 import SizedFileAdapter, determine_part_size
from oss2.models import PartInfo
# 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
# 填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
# yourBucketName填写存储空间名称。
bucket = oss2.Bucket(auth, 'https://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()

相关文档