Source code for b2sdk.transfer.inbound.download_manager

######################################################################
#
# File: b2sdk/transfer/inbound/download_manager.py
#
# Copyright 2020 Backblaze Inc. All Rights Reserved.
#
# License https://www.backblaze.com/using_b2_code.html
#
######################################################################

import logging
from typing import Optional

from b2sdk.encryption.setting import EncryptionSetting
from b2sdk.progress import DoNothingProgressListener

from b2sdk.exception import (
    InvalidRange,
)
from b2sdk.utils import B2TraceMetaAbstract

from .downloaded_file import DownloadedFile
from .downloader.parallel import ParallelDownloader
from .downloader.simple import SimpleDownloader

logger = logging.getLogger(__name__)


[docs]class DownloadManager(metaclass=B2TraceMetaAbstract): """ Handle complex actions around downloads to free raw_api from that responsibility. """ # how many chunks to break a downloaded file into DEFAULT_MAX_STREAMS = 8 # minimum size of a download chunk DEFAULT_MIN_PART_SIZE = 100 * 1024 * 1024 # block size used when downloading file. If it is set to a high value, # progress reporting will be jumpy, if it's too low, it impacts CPU MIN_CHUNK_SIZE = 8192 # ~1MB file will show ~1% progress increment MAX_CHUNK_SIZE = 1024**2
[docs] def __init__(self, services): """ Initialize the DownloadManager using the given services object. :param b2sdk.v2.Services services: """ self.services = services self.strategies = [ ParallelDownloader( max_streams=self.DEFAULT_MAX_STREAMS, min_part_size=self.DEFAULT_MIN_PART_SIZE, min_chunk_size=self.MIN_CHUNK_SIZE, max_chunk_size=self.MAX_CHUNK_SIZE, ), SimpleDownloader( min_chunk_size=self.MIN_CHUNK_SIZE, max_chunk_size=self.MAX_CHUNK_SIZE, ), ]
[docs] def download_file_from_url( self, url, progress_listener=None, range_=None, encryption: Optional[EncryptionSetting] = None, ) -> DownloadedFile: """ :param url: url from which the file should be downloaded :param progress_listener: where to notify about downloading progress :param range_: 2-element tuple containing data of http Range header :param b2sdk.v2.EncryptionSetting encryption: encryption setting (``None`` if unknown) """ progress_listener = progress_listener or DoNothingProgressListener() with self.services.session.download_file_from_url( url, range_=range_, encryption=encryption, ) as response: download_version = self.services.api.download_version_factory.from_response_headers( response.headers ) if range_ is not None: # 2021-05-20: unfortunately for a read of a complete object server does not return the 'Content-Range' header if (range_[1] - range_[0] + 1) != download_version.content_length: raise InvalidRange(download_version.content_length, range_) return DownloadedFile( download_version=download_version, download_manager=self, range_=range_, response=response, encryption=encryption, progress_listener=progress_listener, )