开发者社区 问答 正文

Python-SDK之如何实现上传文件(二)?


分片上传


采用分片上传,用户可以对上传做更为精细的控制。这适用于诸如预先不知道文件大小、并发上传、自定义断点续传等场景。一次分片上传可以分为三个步骤:

  • 初始化(Bucket.init_multipart_upload):获得Upload ID
  • 上传分片(Bucket.upload_part):这一步可以并发进行
  • 完成上传(Bucket.complete_multipart_upload):合并分片,生成OSS文件

具体例子如下:
  1. import os
  2. from oss2 import SizedFileAdapter, determine_part_size
  3. from oss2.models import PartInfo
  4. key = 'remote.txt'
  5. filename = 'local.txt'
  6. total_size = os.path.getsize(filename)
  7. part_size = determine_part_size(total_size, preferred_size=100 * 1024)
  8. # 初始化分片
  9. upload_id = bucket.init_multipart_upload(key).upload_id
  10. parts = []
  11. # 逐个上传分片
  12. with open(filename, 'rb') as fileobj:
  13.     part_number = 1
  14.     offset = 0
  15.     while offset < total_size:
  16.         num_to_upload = min(part_size, total_size - offset)
  17.         result = bucket.upload_part(key, upload_id, part_number,
  18.                                     SizedFileAdapter(fileobj, num_to_upload))
  19.         parts.append(PartInfo(part_number, result.etag))
  20.         offset += num_to_upload
  21.         part_number += 1
  22. # 完成分片上传
  23. bucket.complete_multipart_upload(key, upload_id, parts)
  24. # 验证一下
  25. with open(filename, 'rb') as fileobj:
  26.     assert bucket.get_object(key).read() == fileobj.read()

其中:
  • determine_part_size是一个用来确定分片大小的帮助函数。
  • SizedFileAdapter(fileobj, size)会生成一个新的file object,起始偏移和原先一样,但最多只能读取size大小。

注意:
  • 三个步骤中的对象名(key)必须一致;上传分片和完成上传中的Upload ID必须一致。


追加上传


可以通过Bucket.append_object方法进行追加上传:
  1. result = bucket.append_object('append.txt', 0, 'content of first append')
  2. 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:
  1. bucket.put_object('a.json', '{"age": 1}', headers={'Content-Type': 'application/json; charset=utf-8'})

所能支持的HTTP标准头部列表,请参考API文档中 PutObject部分。

设置自定义元信息


通过传入x-oss-meta-为前缀的HTTP头部,可以为文件设置自定义元信息:
  1. bucket.put_object('story.txt', 'a novel', headers={'x-oss-meta-author': 'O. Henry'})


进度条


上传接口都提供了可选参数progress_callback,用来帮助实现进度条功能。下面的代码以Bucket.put_object为例,实现了一个简单的命令行下的进度显示功能(新开一个Python源文件):
  1. # -*- coding: utf-8 -*-
  2. from __future__ import print_function
  3. import os, sys
  4. import oss2
  5. auth = oss2.Auth('您的AccessKeyId', '您的AccessKeySecret')
  6. bucket = oss2.Bucket(auth, '您的Endpoint', '您的Bucket名')
  7. def percentage(consumed_bytes, total_bytes):
  8.     if total_bytes:
  9.         rate = int(100 * (float(consumed_bytes) / float(total_bytes)))
  10.         print('\r{0}% '.format(rate), end='')
  11.         sys.stdout.flush()
  12. 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为例,实现了一个简单的上传回调功能:
  1. # -*- coding: utf-8 -*-
  2. import json
  3. import base64
  4. import os
  5. import oss2
  6. auth = oss2.Auth('您的AccessKeyId', '您的AccessKeySecret')
  7. bucket = oss2.Bucket(auth, '您的Endpoint', '您的Bucket名')
  8. # 准备回调参数
  9. callback_dict = {}
  10. callback_dict['callbackUrl'] = 'http://oss-demo.aliyuncs.com:23450'
  11. callback_dict['callbackHost'] = 'oss-cn-hangzhou.aliyuncs.com'
  12. callback_dict['callbackBody'] = 'filename=${object}&size=${size}&mimeType=${mimeType}'
  13. callback_dict['callbackBodyType'] = 'application/x-www-form-urlencoded'
  14. # 回调参数是json格式,并且需要base64编码
  15. callback_param = json.dumps(callback_dict).strip()
  16. base64_callback_body = base64.b64encode(callback_param)
  17. # 回调参数编码后放在header中传给oss
  18. headers = {'x-oss-callback': base64_callback_body}
  19. # 上传并回调
  20. result = bucket.put_object('story.txt', 'a'*1024*1024, headers)

提示:
  • 上传回调的详细说明请参看 上传回调
  • 上传回调的完整示例代码请参看 GitHub

展开
收起
青衫无名 2017-10-18 11:30:08 2320 分享 版权
0 条回答
写回答
取消 提交回答