You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is a frequent problem with urllib3 in that the default behavior loads all of the file's data into memory at once before sending resulting in a huge files getting loaded into memory.
It's a hard problem to fix in urllib3 because of how the API was designed, but we can still fix our implementation not to do this. I've got part of a patch for this currently.
One subtlety here is that right now we either support the request content being bytes or a byte iterator. The iterator case can't support body-preserving redirects. So we've actually got a precursor to this issue of supporting a rewindable/seekable type. (To allow rewinding back to the start of the upload.)
Yeah there's some bits and pieces I can lift from urllib3 and some unmerged branches for that specific case. Effectively we add support for passing a seekable object as data and then we implement an file-like interface for the multipart data and internally can rewind the individual file objects when we receive a .seek(0, 0).
Ah yes. Streaming multipart would be a great feature for us to add now, in particular because it doesn't add any new API surface area at all, and the content streams are designed to allow us to support it. 😃
Right now we generate the multipart data on __init__...
Additionally we'd want FileField.render_data to read and return chunks-at-a-time, and be called multiple times, rather than being called once and returning the entire file content.
Activity
lovelydinosaur commentedon Jul 10, 2019
Yup, defo.
One subtlety here is that right now we either support the request content being bytes or a byte iterator. The iterator case can't support body-preserving redirects. So we've actually got a precursor to this issue of supporting a rewindable/seekable type. (To allow rewinding back to the start of the upload.)
sethmlarson commentedon Jul 10, 2019
Yeah there's some bits and pieces I can lift from urllib3 and some unmerged branches for that specific case. Effectively we add support for passing a seekable object as
dataand then we implement an file-like interface for the multipart data and internally can rewind the individual file objects when we receive a.seek(0, 0).Would something like this be effective?
florimondmanca commentedon Mar 5, 2020
Any updated context on this given where we're at now? Is this still an issue/is it easier to tackle, and how?
lovelydinosaur commentedon Mar 9, 2020
Ah yes. Streaming multipart would be a great feature for us to add now, in particular because it doesn't add any new API surface area at all, and the content streams are designed to allow us to support it. 😃
Right now we generate the multipart data on
__init__...httpx/httpx/_content_streams.py
Lines 272 to 288 in 6e40c1b
Instead we should be moving that into
__iter__...httpx/httpx/_content_streams.py
Lines 308 to 309 in 6e40c1b
...and
__aiter__...httpx/httpx/_content_streams.py
Lines 311 to 312 in 6e40c1b
Additionally we'd want
FileField.render_datato read and return chunks-at-a-time, and be called multiple times, rather than being called once and returning the entire file content.florimondmanca commentedon Mar 9, 2020
Okay — looking into it. :-) The bits around estimating the content length without reading the entire data are interesting!