在文件上传场景中,通常会遇到网络中断或其他异常情况导致上传失败的问题。为了避免重复上传浪费带宽和时间,最好支持断点续传功能。阿里云OSS提供了分片上传(Multipart Upload)机制,可以实现断点续传上传。本文将介绍如何使用Python SDK实现OSS断点续传上传功能。

准备工作

在开始之前,您需要准备以下几项内容:

  1. 阿里云OSS账号的AccessKey ID和AccessKey Secret
  2. OSS Bucket名称
  3. 待上传文件的本地路径

实现步骤

  1. 安装阿里云OSS Python SDK
pipinstall oss2
  • 1.
  1. 导入所需的模块并配置必要的参数
import oss2
import os

# 阿里云账号AccessKey信息
access_key_id = '<yourAccessKeyId>'
access_key_secret = '<yourAccessKeySecret>'

# endpoint以杭州为例,其它region请按实际情况填写
endpoint = 'https://oss-cn-hangzhou.aliyuncs.com'
bucket_name = '<yourBucketName>'
object_name = '<yourObjectName>'
local_file = '/local/path/to/file'

# 创建Bucket对象
bucket = oss2.Bucket(oss2.Auth(access_key_id, access_key_secret), endpoint, bucket_name)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  1. 实现断点续传上传函数
# 断点续传上传
upload_id = None
part_size = 102400  # 分片大小,单位字节,最小100KB
position = 0
multipart_upload = None

# 判断是否为新上传或续传
try:
    multipart_upload = bucket.init_multipart_upload(object_name)
    upload_id = multipart_upload.upload_id
except oss2.exceptions.ObjectAlreadyExists:
    upload_id = bucket.init_multipart_upload(object_name).upload_id
    position = bucket.head_object(object_name).content_length

# 开始上传
parts = []
file_size = os.path.getsize(local_file)

with open(local_file, 'rb') as fileobj:
    fileobj.seek(position)
    while position < file_size:
        part_size = min(part_size, file_size - position)
        result = bucket.upload_part(object_name, upload_id, position // part_size + 1, fileobj.read(part_size))
        parts.append(oss2.models.PartInfo(result.part_number, result.etag))
        position += part_size

# 完成上传
if len(parts) > 0:
    bucket.complete_multipart_upload(object_name, upload_id, parts)
else:
    bucket.abort_multipart_upload(object_name, upload_id)

print('upload completed')
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.

代码解释:

  1. 设置分片大小,最小为100KB。
  2. 判断是否为新上传或续传。如果文件已经存在,则获取文件长度作为续传的起始位置。
  3. 如果是新上传,则调用init_multipart_upload方法初始化分片上传;如果是续传,则获取之前分片上传的Upload ID。
  4. 开始分片上传,每次读取指定大小的数据块,调用upload_part方法上传。
  5. 所有分片上传完成后,调用complete_multipart_upload方法完成上传。

需要注意的是:

  • 分片上传时,需要记录每个分片的部分号(part_number)和ETag值。
  • 如果中途发生异常,可以根据Upload ID继续上传剩余的分片。
  • 上传完成后,需要调用complete_multipart_upload方法完成上传,否则会产生碎片文件浪费存储空间。
  • 如果上传过程中出现错误,需要调用abort_multipart_upload方法取消上传,避免产生碎片文件。

总结

通过阿里云OSS的分片上传机制和Python SDK,我们可以轻松实现断点续传上传功能。相比传统的上传方式,断点续传上传可以有效提高上传效率,避免重复上传浪费带宽和时间。在实际项目中,可以根据实际需求进行功能扩展和优化,例如添加进度展示、失败重试等功能。