Skip to content

Commit 0906d22

Browse files
committed
Implementing umbrella Blob.download().
Handles 3 previously supported cases in single method.
1 parent b395360 commit 0906d22

File tree

1 file changed

+65
-16
lines changed

1 file changed

+65
-16
lines changed

gcloud/storage/blob.py

Lines changed: 65 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -216,19 +216,68 @@ def delete(self):
216216
"""
217217
return self.bucket.delete_blob(self)
218218

219-
def download_to_file(self, file_obj):
219+
def download(self, filename_or_buffer=None):
220+
"""Download the contents of this blob.
221+
222+
Supports downloading
223+
- directly as string (via a temporary buffer)
224+
- into a file on the local filesystem
225+
- into an existing buffer (possibly to a file)
226+
227+
If called with no arguments, returns a string::
228+
229+
>>> print blob.download()
230+
'contents-of-blob'
231+
232+
:type filename_or_buffer: string, writable buffer or ``NoneType``
233+
:param filename_or_buffer: An optional filename or a writable buffer
234+
to download contents into.
235+
236+
:raises: :class:`gcloud.exceptions.NotFound`
237+
:rtype: string or ``NoneType``
238+
:returns: The downloaded file if ``filename_or_buffer`` is ``None``.
239+
"""
240+
return_string = update_mtime = False
241+
242+
if filename_or_buffer is None:
243+
buffer_obj = BytesIO()
244+
return_string = True
245+
elif isinstance(filename_or_buffer, six.string_types):
246+
buffer_obj = open(filename_or_buffer, 'wb')
247+
update_mtime = True
248+
else:
249+
buffer_obj = filename_or_buffer
250+
251+
try:
252+
self._download_to_buffer(buffer_obj)
253+
254+
if return_string:
255+
return buffer_obj.getvalue()
256+
finally:
257+
if update_mtime:
258+
buffer_obj.close()
259+
260+
mtime = time.mktime(
261+
datetime.datetime.strptime(
262+
self.properties['updated'],
263+
'%Y-%m-%dT%H:%M:%S.%fz').timetuple()
264+
)
265+
os.utime(buffer_obj.name, (mtime, mtime))
266+
267+
def _download_to_buffer(self, buffer_obj):
220268
"""Download the contents of this blob into a file-like object.
221269
222-
:type file_obj: file
223-
:param file_obj: A file handle to which to write the blob's data.
270+
:type buffer_obj: writable object
271+
:param buffer_obj: A buffer object with a write() method.
224272
225273
:raises: :class:`gcloud.exceptions.NotFound`
226274
"""
227275

228276
download_url = self.media_link
229277

230278
# Use apitools 'Download' facility.
231-
download = transfer.Download.FromStream(file_obj, auto_transfer=False)
279+
download = transfer.Download.FromStream(buffer_obj,
280+
auto_transfer=False)
232281
download.chunksize = self.CHUNK_SIZE
233282
headers = {'Range': 'bytes=0-%d' % (self.CHUNK_SIZE - 1)}
234283
request = http_wrapper.Request(download_url, 'GET', headers)
@@ -241,6 +290,16 @@ def download_to_file(self, file_obj):
241290
download.StreamInChunks(callback=lambda *args: None,
242291
finish_callback=lambda *args: None)
243292

293+
def download_to_file(self, file_obj):
294+
"""Download the contents of this blob into a file-like object.
295+
296+
:type file_obj: file
297+
:param file_obj: A file handle to which to write the blob's data.
298+
299+
:raises: :class:`gcloud.exceptions.NotFound`
300+
"""
301+
self.download(file_obj)
302+
244303
def download_to_filename(self, filename):
245304
"""Download the contents of this blob into a named file.
246305
@@ -249,15 +308,7 @@ def download_to_filename(self, filename):
249308
250309
:raises: :class:`gcloud.exceptions.NotFound`
251310
"""
252-
with open(filename, 'wb') as file_obj:
253-
self.download_to_file(file_obj)
254-
255-
mtime = time.mktime(
256-
datetime.datetime.strptime(
257-
self.properties['updated'],
258-
'%Y-%m-%dT%H:%M:%S.%fz').timetuple()
259-
)
260-
os.utime(file_obj.name, (mtime, mtime))
311+
self.download(filename)
261312

262313
def download_as_string(self):
263314
"""Download the contents of this blob as a string.
@@ -266,9 +317,7 @@ def download_as_string(self):
266317
:returns: The data stored in this blob.
267318
:raises: :class:`gcloud.exceptions.NotFound`
268319
"""
269-
string_buffer = BytesIO()
270-
self.download_to_file(string_buffer)
271-
return string_buffer.getvalue()
320+
return self.download()
272321

273322
def upload_from_file(self, file_obj, rewind=False, size=None,
274323
content_type=None, num_retries=6):

0 commit comments

Comments
 (0)