4343from google import resumable_media
4444from google.resumable_media.requests import ChunkedDownload
4545from google.resumable_media.requests import Download
46+ from google.resumable_media.requests import RawDownload
47+ from google.resumable_media.requests import RawChunkedDownload
4648from google.resumable_media.requests import MultipartUpload
4749from google.resumable_media.requests import ResumableUpload
4850
@@ -591,7 +593,14 @@ def _get_download_url(self):
591593 return _add_query_parameters(base_url, name_value_pairs)
592594
593595 def _do_download(
594- self, transport, file_obj, download_url, headers, start=None, end=None
596+ self,
597+ transport,
598+ file_obj,
599+ download_url,
600+ headers,
601+ start=None,
602+ end=None,
603+ raw_download=False,
595604 ):
596605 """Perform a download without any error handling.
597606
@@ -617,14 +626,30 @@ def _do_download(
617626
618627 :type end: int
619628 :param end: Optional, The last byte in a range to be downloaded.
629+
630+ :type raw_download: bool
631+ :param raw_download:
632+ Optional, If true, download the object without any expansion.
620633 """
621634 if self.chunk_size is None:
622- download = Download(
635+ if raw_download:
636+ klass = RawDownload
637+ else:
638+ klass = Download
639+
640+ download = klass(
623641 download_url, stream=file_obj, headers=headers, start=start, end=end
624642 )
625643 download.consume(transport)
644+
626645 else:
627- download = ChunkedDownload(
646+
647+ if raw_download:
648+ klass = RawChunkedDownload
649+ else:
650+ klass = ChunkedDownload
651+
652+ download = klass(
628653 download_url,
629654 self.chunk_size,
630655 file_obj,
@@ -636,7 +661,9 @@ def _do_download(
636661 while not download.finished:
637662 download.consume_next_chunk(transport)
638663
639- def download_to_file(self, file_obj, client=None, start=None, end=None):
664+ def download_to_file(
665+ self, file_obj, client=None, start=None, end=None, raw_download=False
666+ ):
640667 """Download the contents of this blob into a file-like object.
641668
642669 .. note::
@@ -676,6 +703,10 @@ def download_to_file(self, file_obj, client=None, start=None, end=None):
676703 :type end: int
677704 :param end: Optional, The last byte in a range to be downloaded.
678705
706+ :type raw_download: bool
707+ :param raw_download:
708+ Optional, If true, download the object without any expansion.
709+
679710 :raises: :class:`google.cloud.exceptions.NotFound`
680711 """
681712 download_url = self._get_download_url()
@@ -684,11 +715,15 @@ def download_to_file(self, file_obj, client=None, start=None, end=None):
684715
685716 transport = self._get_transport(client)
686717 try:
687- self._do_download(transport, file_obj, download_url, headers, start, end)
718+ self._do_download(
719+ transport, file_obj, download_url, headers, start, end, raw_download
720+ )
688721 except resumable_media.InvalidResponse as exc:
689722 _raise_from_invalid_response(exc)
690723
691- def download_to_filename(self, filename, client=None, start=None, end=None):
724+ def download_to_filename(
725+ self, filename, client=None, start=None, end=None, raw_download=False
726+ ):
692727 """Download the contents of this blob into a named file.
693728
694729 If :attr:`user_project` is set on the bucket, bills the API request
@@ -708,11 +743,21 @@ def download_to_filename(self, filename, client=None, start=None, end=None):
708743 :type end: int
709744 :param end: Optional, The last byte in a range to be downloaded.
710745
746+ :type raw_download: bool
747+ :param raw_download:
748+ Optional, If true, download the object without any expansion.
749+
711750 :raises: :class:`google.cloud.exceptions.NotFound`
712751 """
713752 try:
714753 with open(filename, "wb") as file_obj:
715- self.download_to_file(file_obj, client=client, start=start, end=end)
754+ self.download_to_file(
755+ file_obj,
756+ client=client,
757+ start=start,
758+ end=end,
759+ raw_download=raw_download,
760+ )
716761 except resumable_media.DataCorruption:
717762 # Delete the corrupt downloaded file.
718763 os.remove(filename)
@@ -723,7 +768,7 @@ def download_to_filename(self, filename, client=None, start=None, end=None):
723768 mtime = time.mktime(updated.timetuple())
724769 os.utime(file_obj.name, (mtime, mtime))
725770
726- def download_as_string(self, client=None, start=None, end=None):
771+ def download_as_string(self, client=None, start=None, end=None, raw_download=False ):
727772 """Download the contents of this blob as a bytes object.
728773
729774 If :attr:`user_project` is set on the bucket, bills the API request
@@ -740,12 +785,22 @@ def download_as_string(self, client=None, start=None, end=None):
740785 :type end: int
741786 :param end: Optional, The last byte in a range to be downloaded.
742787
788+ :type raw_download: bool
789+ :param raw_download:
790+ Optional, If true, download the object without any expansion.
791+
743792 :rtype: bytes
744793 :returns: The data stored in this blob.
745794 :raises: :class:`google.cloud.exceptions.NotFound`
746795 """
747796 string_buffer = BytesIO()
748- self.download_to_file(string_buffer, client=client, start=start, end=end)
797+ self.download_to_file(
798+ string_buffer,
799+ client=client,
800+ start=start,
801+ end=end,
802+ raw_download=raw_download,
803+ )
749804 return string_buffer.getvalue()
750805
751806 def _get_content_type(self, content_type, filename=None):
0 commit comments