I'm uploading potentially large files to a web server. Currently I'm doing this:
import urllib2
f = open('somelargefile.zip','rb')
request = urllib2.Request(url,f.read())
request.add_header("Content-Type", "application/zip")
response = urllib2.urlopen(request)
However, this reads the entire file's contents into memory before posting it. How can I have it stream the file to the server?
Reading through the mailing list thread linked to by systempuntoout, I found a clue towards the solution.
The
mmap
module allows you to open file that acts like a string. Parts of the file are loaded into memory on demand.Here's the code I'm using now:
Using the
requests
library you can doas mentioned here in their docs
The documentation doesn't say you can do this, but the code in urllib2 (and httplib) accepts any object with a read() method as data. So using an open file seems to do the trick.
You'll need to set the Content-Length header yourself. If it's not set, urllib2 will call len() on the data, which file objects don't support.
This is the relevant code that handles the data you supply. It's from the
HTTPConnection
class inhttplib.py
in Python 2.7:Try pycurl. I don't have anything setup will accept a large file that isn't in a multipart/form-data POST, but here's a simple example that reads the file as needed.
Cannot (yet) comment on Brian's answer https://stackoverflow.com/a/30810626/9921853
urllib2.urlopen(url, data, headers) doesn't take headers as parameter, so it won't work
Below is the working example for both Python 2 / Python 3:
The requests module is great, but sometimes you cannot install any extra modules...
Have you tried with Mechanize?
or, if you don't want to use multipart/form-data, check this old post.
It suggests two options: