Skip to content

Storage: google-resumable-media==0.4.0 Breaks Gzipped Downloads #9188

Closed

Description

@william-silversmith

Environment details

  1. Specify the API at the beginning of the title (for example, "BigQuery: ...")
    General, Core, and Other are also allowed as types

Google Storage blob.py

  1. OS type and version

Ubuntu 14.04

  1. Python version and virtual environment information: python --version

Python 3.6.8

  1. google-cloud- version: pip show google-<service> or pip freeze

google-cloud-storage==1.19.0

Steps to reproduce

  1. pip install google-resumable-media==0.4.0
  2. blob.download_as_string()

Per the latest release of google-resumable-media, no decompression of content-encoding gzip is performed and raw bytes are returned.

See https://github.com/googleapis/google-resumable-media-python/releases

blob.download_as_string() formerly returned decompressed bytes, and now returns compressed bytes. We are using .blob instead of .get_blob for an HPC application and thus have no way of knowing what the content encoding is as the information is erased.

We actually LIKE the new functionality as we can now decide when to decompress, but we need to know the content encoding to avoid various kinds of problems that would be introduced by speculative decompression.

Code example

Here is our desired functionality.

    blob = bucket.blob( key )
    try:
      # blob handles the decompression so the encoding is None
      resp = blob.download_as_string(start=start, end=end)
      return resp, blob.content_encoding
    except google.cloud.exceptions.NotFound as err:
      return None, None

Adding this patch to google.cloud.storage.blob.py would solve this problem for us:

    def _do_download(
        self, transport, file_obj, download_url, headers, start=None, end=None
    ):
        """Perform a download without any error handling.

        This is intended to be called by :meth:`download_to_file` so it can
        be wrapped with error handling / remapping.

        :type transport:
            :class:`~google.auth.transport.requests.AuthorizedSession`
        :param transport: The transport (with credentials) that will
                          make authenticated requests.

        :type file_obj: file
        :param file_obj: A file handle to which to write the blob's data.

        :type download_url: str
        :param download_url: The URL where the media can be accessed.

        :type headers: dict
        :param headers: Optional headers to be sent with the request(s).

        :type start: int
        :param start: Optional, the first byte in a range to be downloaded.

        :type end: int
        :param end: Optional, The last byte in a range to be downloaded.
        """
        if self.chunk_size is None:
            download = Download(
                download_url, stream=file_obj, headers=headers, start=start, end=end
            )
>           response = download.consume(transport)
>           if 'Content-Encoding' in response.headers:
>               self.content_encoding = response.headers['Content-Encoding']
        else:
            download = ChunkedDownload(
                download_url,
                self.chunk_size,
                file_obj,
                headers=headers,
                start=start if start else 0,
                end=end,
            )

            while not download.finished:
                download.consume_next_chunk(transport)

Activity

  1. added
    type: questionRequest for information or clarification. Not an issue.
    type: feature request‘Nice-to-have’ improvement, new feature or different behavior or design.
    api: storageIssues related to the Cloud Storage API.
    and removed
    triage meI really want to be triaged.
    type: questionRequest for information or clarification. Not an issue.
    on Sep 9, 2019
  2. tseaver commented on Sep 9, 2019

    @tseaver
    Contributor

    @william-silversmith Can you achieve what you need to reloading the blob's metadata? E.g.:

    blob.reload()

    At that point, the content_encoding property will be populated from the server.

  3. william-silversmith commented on Sep 9, 2019

    @william-silversmith
    ContributorAuthor
  4. tseaver commented on Sep 9, 2019

    @tseaver
    Contributor

    @william-silversmith Thanks for clarifying. One issue here is that we would want to have the header-driven content_encoding value also available for chunked downloads, so we would need to rework your patch a bit.

    @crwilcox, @frankyn Please chime in.

  5. changed the title [-]storage.blob: google-resumable-media==0.4.0 Breaks Gzipped Downloads[/-] [+]Storage: google-resumable-media==0.4.0 Breaks Gzipped Downloads[/+] on Sep 10, 2019
  6. frankyn commented on Sep 17, 2019

    @frankyn
    Contributor

    @crwilcox reverted changes made in googleapis/google-resumable-media-python#103 and releasing a new version to unblock this issue: googleapis/google-resumable-media-python#104

    Reassigning to him.

  7. added
    type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.
    and removed
    type: feature request‘Nice-to-have’ improvement, new feature or different behavior or design.
    on Sep 17, 2019
  8. assigned and unassigned on Sep 17, 2019
  9. crwilcox commented on Sep 17, 2019

    @crwilcox
    Contributor

    Hi @william-silversmith I have released v0.4.1 that backs out this change.

    Due to the way we have pinned this package within google-cloud-storage, we are rethinking the way we make this change to avoid disrupting folks using existing libraries.

  10. william-silversmith commented on Sep 17, 2019

    @william-silversmith
    ContributorAuthor

    Thank you very much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

🚨This issue needs some love.api: storageIssues related to the Cloud Storage API.triage meI really want to be triaged.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions