in oss2/resumable.py [0:0]
def resumable_download(bucket, key, filename,
multiget_threshold=None,
part_size=None,
progress_callback=None,
num_threads=None,
store=None,
params=None,
headers=None):
"""断点下载。
实现的方法是:
#. 在本地创建一个临时文件,文件名由原始文件名加上一个随机的后缀组成;
#. 通过指定请求的 `Range` 头按照范围并发读取OSS文件,并写入到临时文件里对应的位置;
#. 全部完成之后,把临时文件重命名为目标文件 (即 `filename` )
在上述过程中,断点信息,即已经完成的范围,会保存在磁盘上。因为某种原因下载中断,后续如果下载
同样的文件,也就是源文件和目标文件一样,就会先读取断点信息,然后只下载缺失的部分。
缺省设置下,断点信息保存在 `HOME` 目录的一个子目录下。可以通过 `store` 参数更改保存位置。
使用该函数应注意如下细节:
#. 对同样的源文件、目标文件,避免多个程序(线程)同时调用该函数。因为断点信息会在磁盘上互相覆盖,或临时文件名会冲突。
#. 避免使用太小的范围(分片),即 `part_size` 不宜过小,建议大于或等于 `oss2.defaults.multiget_part_size` 。
#. 如果目标文件已经存在,那么该函数会覆盖此文件。
#. 如果使用CryptoBucket,函数会退化为普通下载
:param bucket: :class:`Bucket <oss2.Bucket>` 或者 ::class:`CryptoBucket <oss2.CryptoBucket>` 对象
:param str key: 待下载的远程文件名。
:param str filename: 本地的目标文件名。
:param int multiget_threshold: 文件长度大于该值时,则使用断点下载。
:param int part_size: 指定期望的分片大小,即每个请求获得的字节数,实际的分片大小可能有所不同。
:param progress_callback: 下载进度回调函数。参见 :ref:`progress_callback` 。
:param num_threads: 并发下载的线程数,如不指定则使用 `oss2.defaults.multiget_num_threads` 。
:param store: 用来保存断点信息的持久存储,可以指定断点信息所在的目录。
:type store: `ResumableDownloadStore`
:param dict params: 指定下载参数,可以传入versionId下载指定版本文件
:param headers: HTTP头部,
# 调用外部函数head_object目前只传递OSS_REQUEST_PAYER
# 调用外部函数get_object_to_file, get_object目前需要向下传递的值有OSS_REQUEST_PAYER, OSS_TRAFFIC_LIMIT
:type headers: 可以是dict,建议是oss2.CaseInsensitiveDict
:raises: 如果OSS文件不存在,则抛出 :class:`NotFound <oss2.exceptions.NotFound>` ;也有可能抛出其他因下载文件而产生的异常。
"""
logger.debug("Start to resumable download, bucket: {0}, key: {1}, filename: {2}, multiget_threshold: {3}, "
"part_size: {4}, num_threads: {5}".format(bucket.bucket_name, to_string(key), filename,
multiget_threshold, part_size, num_threads))
multiget_threshold = defaults.get(multiget_threshold, defaults.multiget_threshold)
valid_headers = _populate_valid_headers(headers, [OSS_REQUEST_PAYER, OSS_TRAFFIC_LIMIT])
result = bucket.head_object(key, params=params, headers=valid_headers)
logger.debug("The size of object to download is: {0}, multiget_threshold: {1}".format(result.content_length,
multiget_threshold))
if result.content_length >= multiget_threshold:
downloader = _ResumableDownloader(bucket, key, filename, _ObjectInfo.make(result), part_size=part_size,
progress_callback=progress_callback, num_threads=num_threads, store=store,
params=params, headers=valid_headers)
downloader.download(result.server_crc)
else:
bucket.get_object_to_file(key, filename, progress_callback=progress_callback, params=params,
headers=valid_headers)