So I've been playing around with raw WSGI, cgi.FieldStorage and file uploads. And I just can't understand how it deals with file uploads.
At first it seemed that it just stores the whole file in memory. And I thought hm, that should be easy to test - a big file should clog up the memory!.. And it didn't. Still, when I request the file, it's a string, not an iterator, file object or anything.
I've tried reading the cgi module's source and found some things about temporary files, but it returns a freaking string, not a file(-like) object! So... how does it fscking work?!
Here's the code I've used:
import cgi
from wsgiref.simple_server import make_server
def app(environ,start_response):
start_response('200 OK',[('Content-Type','text/html')])
output = """
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="failas" />
<input type="submit" value="Varom" />
</form>
"""
fs = cgi.FieldStorage(fp=environ['wsgi.input'],environ=environ)
f = fs.getfirst('failas')
print type(f)
return output
if __name__ == '__main__' :
httpd = make_server('',8000,app)
print 'Serving'
httpd.serve_forever()
Thanks in advance! :)
Inspecting the cgi module description, there is a paragraph discussing how to handle file uploads.
Regarding your example,
getfirst()
is just a version ofgetvalue()
. try replacingwith
This will return a file-like object that is readable "at leisure".
The best way is to NOT to read file (or even each line at a time as gimel suggested).
You can use some inheritance and extend a class from FieldStorage and then override make_file function. make_file is called when FieldStorage is of type file.
For your reference, default make_file looks like this:
rather then creating temporaryfile, permanently create file wherever you want.
Using an answer by @hasanatkazmi (utilized in a Twisted app) I got something like:
Be warned, that the file is not always created by the cgi module. According to these
cgi.py
lines it will only be created if the content exceeds 1000 bytes:So, you have to check if the file was actually created with a query to a custom class'
path
field like so:If the
Content-Length
is also set for the field, which seems rarely, the file should also be created by cgi.That's it. This way you can store the file predictably, decreasing the memory usage footprint of your app.