I have a cherrypy web server that needs to be able to receive large files over http post. I have something working at the moment, but it fails once the files being sent gets too big (around 200mb). I'm using curl to send test post requests, and when I try to send a file that's too big, curl spits out "The entity sent with the request exceeds the maximum allowed bytes." Searching around, this seems to be an error from cherrypy.
So I'm guessing that the file being sent needs to be sent in chunks? I tried something with mmap, but I couldn't get it too work. Does the method that handles the file upload need to be able to accept the data in chunks too?
I took
DirectToDiskFileUpload
as a starting point. The changes it makes to handle big uploads are:server.max_request_body_size
to0
(default 100MB),server.socket_timeout
to60
(default 10s),response.timeout
to3600
(default 300s),tempfile.NamedTemporaryFile
.There are also some useless actions taken to supposedly avoid holding upload in memory, which disable standard CherryPy body processing and use
cgi.FieldStorage
manually instead. It is useless because there ischerrypy._cpreqbody.Part.maxrambytes
.I've experimented with the following code (run by Python 2.7.4, CherryPy 3.6) and 1.4GB file. Memory usage (in gnome-system-monitor) never reached out 10MiB. According to the number of bytes actually written to the disk,
cat /proc/PID/io
'swrite_bytes
is almost the size of the file. With standardcherrypy._cpreqbody.Part
andshutil.copyfileobj
it is obviously doubled.Huge file uploads always problematic. What would you do when connection closes in the middle of uploading? Use chunked file upload method instead.