in gslib/boto_translation.py [0:0]
def GetObjectMedia(self,
bucket_name,
object_name,
download_stream,
provider=None,
generation=None,
object_size=None,
compressed_encoding=False,
download_strategy=CloudApi.DownloadStrategy.ONE_SHOT,
start_byte=0,
end_byte=None,
progress_callback=None,
serialization_data=None,
digesters=None,
decryption_tuple=None):
"""See CloudApi class for function doc strings."""
# This implementation will get the object metadata first if we don't pass it
# in via serialization_data.
headers = self._CreateBaseHeaders()
AddAcceptEncodingGzipIfNeeded(headers,
compressed_encoding=compressed_encoding)
if end_byte is not None:
headers['range'] = 'bytes=%s-%s' % (start_byte, end_byte)
elif start_byte > 0:
headers['range'] = 'bytes=%s-' % (start_byte)
elif start_byte < 0:
headers['range'] = 'bytes=%s' % (start_byte)
# Since in most cases we already made a call to get the object metadata,
# here we avoid an extra HTTP call by unpickling the key. This is coupled
# with the implementation in _BotoKeyToObject.
if serialization_data:
serialization_dict = json.loads(serialization_data)
key = pickle.loads(binascii.a2b_base64(serialization_dict['url']))
if self.provider == 'gs':
_AddCustomEndpointToKey(key)
else:
key = self._GetBotoKey(bucket_name, object_name, generation=generation)
if digesters and self.provider == 'gs':
hash_algs = {}
for alg in digesters:
hash_algs[alg] = self._CurryDigester(digesters[alg])
else:
hash_algs = {}
total_size = object_size or 0
if serialization_data:
total_size = json.loads(serialization_data)['total_size']
if total_size:
num_progress_callbacks = max(
int(total_size) / TWO_MIB, XML_PROGRESS_CALLBACKS)
else:
num_progress_callbacks = XML_PROGRESS_CALLBACKS
try:
if download_strategy is CloudApi.DownloadStrategy.RESUMABLE:
self._PerformResumableDownload(download_stream,
start_byte,
end_byte,
key,
headers=headers,
callback=progress_callback,
num_callbacks=num_progress_callbacks,
hash_algs=hash_algs)
elif download_strategy is CloudApi.DownloadStrategy.ONE_SHOT:
self._PerformSimpleDownload(
download_stream,
key,
progress_callback=progress_callback,
num_progress_callbacks=num_progress_callbacks,
headers=headers,
hash_algs=hash_algs)
else:
raise ArgumentException('Unsupported DownloadStrategy: %s' %
download_strategy)
except TRANSLATABLE_BOTO_EXCEPTIONS as e:
self._TranslateExceptionAndRaise(e,
bucket_name=bucket_name,
object_name=object_name,
generation=generation)
if self.provider == 's3':
if digesters:
class HashToDigester(object):
"""Wrapper class to expose hash digests.
boto creates its own digesters in s3's get_file, returning on-the-fly
hashes only by way of key.local_hashes. To propagate the digest back
to the caller, this stub class implements the digest() function.
"""
def __init__(self, hash_val):
self.hash_val = hash_val
def digest(self): # pylint: disable=invalid-name
return self.hash_val
for alg_name in digesters:
if ((download_strategy == CloudApi.DownloadStrategy.RESUMABLE and
start_byte != 0) or not ((getattr(key, 'local_hashes', None) and
alg_name in key.local_hashes))):
# For resumable downloads, boto does not provide a mechanism to
# catch up the hash in the case of a partially complete download.
# In this case or in the case where no digest was successfully
# calculated, set the digester to None, which indicates that we'll
# need to manually calculate the hash from the local file once it
# is complete.
digesters[alg_name] = None
else:
# Use the on-the-fly hash.
digesters[alg_name] = HashToDigester(key.local_hashes[alg_name])