Skip to content

storage: a way to specify Content-Length during upload #601

Description

@gmiroshnykov

Cloud Storage docs mention that you have to specify Content-Length header for upload requests, but I guess this is not a hard requirement as gcloud-node does not do that (as far as I can see) and provides an API for streaming uploads of unknown length using Transfer-Encoding: chunked.

I'd like to be able to explicitly set a known Content-Length in advance.

This might help catching the kind of programmer mistake (which I am guilty of) when you're piping an HTTP request into a stream returned by file.createWriteStream(), but accidentally aborting the HTTP request prematurely. In that case CRC32 / MD5 checksums won't save you because the actual bytes are intact and the upload was technically complete, but logically incomplete.

Activity

  1. added
    type: questionRequest for information or clarification. Not an issue.
    api: storageIssues related to the Cloud Storage API.
    on May 15, 2015
  2. added this to the Storage Future milestone on May 15, 2015
  3. ryanseys commented on May 17, 2015

    @ryanseys
    Contributor

    Would you like to set X-Upload-Content-Length or Content-Length ?

    From the docs:

    X-Upload-Content-Length. Set to the number of bytes of upload data to be transferred in subsequent requests. If the length is unknown at the time of this request, you can omit this header.

    Content-Length. Set to the number of bytes provided in the body of this initial request. Not required if you are using chunked transfer encoding.

    POST /upload/storage/v1/b/myBucket/o?uploadType=resumable HTTP/1.1
    Host: www.googleapis.com
    Authorization: Bearer your_auth_token
    Content-Length: 38
    Content-Type: application/json; charset=UTF-8
    X-Upload-Content-Type: image/jpeg
    X-Upload-Content-Length: 2000000
    
    {
      "name": "myObject"
    }
    
  4. gmiroshnykov commented on May 17, 2015

    @gmiroshnykov
    Author

    It's not about resumable uploads, it's about simple ("multipart") uploads, so X-Upload-Content-Length is not applicable.

    I'd like to be able to set Content-Length and avoid chunked transfer encoding.

  5. stephenplusplus commented on Aug 15, 2015

    @stephenplusplus
    Contributor

    Sorry that 3 months have gone by without any action on this issue. Requests are indeed going through with chunked encoding, and there isn't a way to disable that currently. We could turn it off with your provided Content-Length header, then add on the length of the other part of the request, the metadata, and the upload will only succeed if all of the data is present.

    I think we should definitely support that, but we just need to figure out how and what makes the most sense. The nice thing about streaming uploads is the fact that chunked encoding works to flush data as it's brought through the pipeline. By making a one-off upload, all of that data has to be stored in memory until the request ends. However, that's kind of expected, since you'll probably only want to use a single HTTP request for those smaller sized uploads.

    What do you think about letting file.createWriteStream continue to chunk, but allow bucket.upload to set the Content Length if the file provided is < 5 MB?

    This might help catching the kind of programmer mistake (which I am guilty of) when you're piping an HTTP request into a stream returned by file.createWriteStream(), but accidentally aborting the HTTP request prematurely.

    How would you see this working, since file.createWriteStream() needs to know the content length of the incoming data up front in order to disable chunking?

    Sorry again about the delay. Thanks for bringing this up!

  6. gmiroshnykov commented on Sep 8, 2015

    @gmiroshnykov
    Author

    Hey, thanks and sorry for the delay on my part.

    The nice thing about streaming uploads is the fact that chunked encoding works to flush data as it's brought through the pipeline. By making a one-off upload, all of that data has to be stored in memory until the request ends.

    Actually you can do streaming uploads without chunked encoding or in-memory buffering: just pipe some streams and you'll be fine. But obviously you have to know the exact size of your request in advance, so you could send Content-Length header.

    What do you think about letting file.createWriteStream continue to chunk, but allow bucket.upload to set the Content Length if the file provided is < 5 MB?

    That might be a good idea in itself, but won't help my particular use case.

    I am (was) writing a proxy server that is backed by GCS. On cache miss, I did an HTTP request to the origin server and got an instance of http.IncomingMessage with a known Content-Length header.
    Then I've used file.createWriteStream() and piped the origin response into it (to populate the cache). This way there was no in-memory buffering: I just piped one HTTP GET response into another HTTP POST request. So there was no need for chunked encoding or multipart uploads, but I couldn't pass Content-Length along and instead was forced to use chunked encoding and resumable uploads anyway because that was the only API available when using gcloud-node (at least at that time).

    How would you see this working, since file.createWriteStream() needs to know the content length of the incoming data up front in order to disable chunking?

    I've started looking through the code and it looks like you've changed a bunch of things (great work btw!) and my knowledge is now outdated, plus my original project is done and it works as is, but let me try to suggest a sensible API change:

    It looks like you allow setting a Content-Type via metadata.contentType here. You could also accept metadata.contentLength if it's provided. You'll probably have to ignore it for resumable uploads.

    I hope that made sense :)

    Thanks for your work!

  7. stephenplusplus commented on Sep 8, 2015

    @stephenplusplus
    Contributor

    Thank you for the nice words and for sharing the use case! I put together a PR to support this, please take a look if you're still interested: #853.

  8. stephenplusplus commented on Sep 18, 2015

    @stephenplusplus
    Contributor

    As mentioned here, I'm currently stuck on how to proceed. Feel free to share thoughts here if this feature is really in demand, but for now, I'm going to consider this a micro-optimization that adds too much complexity to the library to support.

  9. 7 remaining items

  10. added a commit that references this issue on Jan 25, 2023
  11. added a commit that references this issue on Jan 28, 2026
  12. added a commit that references this issue on Feb 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

api: storageIssues related to the Cloud Storage API.type: questionRequest for information or clarification. Not an issue.

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions