分片上传
采用分片上传,用户可以对上传做更为精细的控制。这适用于诸如预先不知道文件大小、并发上传、自定义断点续传等场景。一次分片上传可以分为三个步骤:
- 初始化(Bucket.init_multipart_upload):获得Upload ID
- 上传分片(Bucket.upload_part):这一步可以并发进行
- 完成上传(Bucket.complete_multipart_upload):合并分片,生成OSS文件
具体例子如下:
- import os
- from oss2 import SizedFileAdapter, determine_part_size
- from oss2.models import PartInfo
- key = 'remote.txt'
- filename = 'local.txt'
- total_size = os.path.getsize(filename)
- 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)
- 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
- # 完成分片上传
- bucket.complete_multipart_upload(key, upload_id, parts)
- # 验证一下
- with open(filename, 'rb') as fileobj:
- assert bucket.get_object(key).read() == fileobj.read()
其中:
- determine_part_size是一个用来确定分片大小的帮助函数。
- SizedFileAdapter(fileobj, size)会生成一个新的file object,起始偏移和原先一样,但最多只能读取size大小。
注意:
- 三个步骤中的对象名(key)必须一致;上传分片和完成上传中的Upload ID必须一致。
追加上传
可以通过Bucket.append_object方法进行追加上传:
- result = bucket.append_object('append.txt', 0, 'content of first append')
- bucket.append_object('append.txt', result.next_position, 'content of second append')
首次上传的偏移量(position参数)设为0。如果文件已经存在,且
- 不是可追加文件,则抛出ObjectNotAppendable异常;
- 是可追加文件,如果传入的偏移和文件当前长度不等,则抛出PositionNotEqualToLength异常。
如果不是首次上传,可以通过Bucket.head_object方法或上次追加返回值的next_position属性,得到偏移参数。
设置HTTP头
上传时,可以通过headers参数设置OSS支持的HTTP头部,如Content-Type:
- bucket.put_object('a.json', '{"age": 1}', headers={'Content-Type': 'application/json; charset=utf-8'})
所能支持的HTTP标准头部列表,请参考API文档中
PutObject部分。
设置自定义元信息
通过传入x-oss-meta-为前缀的HTTP头部,可以为文件设置自定义元信息:
- bucket.put_object('story.txt', 'a novel', headers={'x-oss-meta-author': 'O. Henry'})
进度条
上传接口都提供了可选参数progress_callback,用来帮助实现进度条功能。下面的代码以Bucket.put_object为例,实现了一个简单的命令行下的进度显示功能(新开一个Python源文件):
- # -*- coding: utf-8 -*-
- from __future__ import print_function
- import os, sys
- import oss2
- auth = oss2.Auth('您的AccessKeyId', '您的AccessKeySecret')
- bucket = oss2.Bucket(auth, '您的Endpoint', '您的Bucket名')
- def percentage(consumed_bytes, total_bytes):
- if total_bytes:
- rate = int(100 * (float(consumed_bytes) / float(total_bytes)))
- print('\r{0}% '.format(rate), end='')
- sys.stdout.flush()
- bucket.put_object('story.txt', 'a'*1024*1024, progress_callback=percentage)
注意:
- 当无法确定待上传的数据长度时,progress_callback的第二个参数(total_bytes)为None。
- 进度条的完整示例代码请参看 GitHub 。
上传回调
put_object、put_object_from_file、complete_multipart_upload提供提供了上传回调功能。下面的代码以Bucket.put_object为例,实现了一个简单的上传回调功能:
- # -*- coding: utf-8 -*-
- import json
- import base64
- import os
- import oss2
- auth = oss2.Auth('您的AccessKeyId', '您的AccessKeySecret')
- bucket = oss2.Bucket(auth, '您的Endpoint', '您的Bucket名')
- # 准备回调参数
- callback_dict = {}
- callback_dict['callbackUrl'] = 'http://oss-demo.aliyuncs.com:23450'
- callback_dict['callbackHost'] = 'oss-cn-hangzhou.aliyuncs.com'
- callback_dict['callbackBody'] = 'filename=${object}&size=${size}&mimeType=${mimeType}'
- callback_dict['callbackBodyType'] = 'application/x-www-form-urlencoded'
- # 回调参数是json格式,并且需要base64编码
- callback_param = json.dumps(callback_dict).strip()
- base64_callback_body = base64.b64encode(callback_param)
- # 回调参数编码后放在header中传给oss
- headers = {'x-oss-callback': base64_callback_body}
- # 上传并回调
- result = bucket.put_object('story.txt', 'a'*1024*1024, headers)
提示: