We help IT Professionals succeed at work.

Python file upload progress bar with javascript

mateomtb
mateomtb used Ask the Experts™
on
I have this basic file upload script working from a tutorial I found linked to from around here. I have it all working and am now trying to get a browser side progress bar working, the files being uploaded are 200MB+ and some sort of status is needed. From some reading around here my thoughts are that python should be able to deliver some sort of current status that I can send to a javascript function.

html
<html><body>
<form enctype="multipart/form-data" action="uploadtest.py" method="post">
<p>File: <input type="file" name="file"></p>
<p><input type="submit" value="Upload"></p>
</form>
</body></html>

Open in new window


python (uploadtest.py)
#!/usr/bin/python
import cgi, os
import cgitb; cgitb.enable()

try: # Windows needs stdio set for binary mode.
    import msvcrt
    msvcrt.setmode (0, os.O_BINARY) # stdin  = 0
    msvcrt.setmode (1, os.O_BINARY) # stdout = 1
except ImportError:
    pass

form = cgi.FieldStorage()

# Generator to buffer file chunks
def fbuffer(f, chunk_size=10000):
   while True:
      chunk = f.read(chunk_size)
      if not chunk: break
      yield chunk
      
# A nested FieldStorage instance holds the file
fileitem = form['file']

# Test if the file was uploaded
if fileitem.filename:

   # strip leading path from file name to avoid directory traversal attacks
   fn = os.path.basename(fileitem.filename)
   f = open('files/' + fn, 'wb', 10000)

   # Read the file in chunks
   for chunk in fbuffer(fileitem.file):
      f.write(chunk)
   f.close()
   message = 'The file "' + fn + '" was uploaded successfully'

else:
   message = 'No file was uploaded'
   
print """\
Content-Type: text/html\n
<html><body>
<p>%s</p>
</body></html>
""" % (message,)

Open in new window


Javascript example I found around here.
<div width="200px" height="30px" ><img height="30px" width="1px" id="loader" src="loader.jpg" /></div>

<script type="text/javascript">

function progress(percent)
{
  document.getElementById('loader').width=Math.round(percent/200);
}

</script>

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Up to my knowledge implementing a progress bar isn't that easy.

The solution might depend on your web server and its version.

If you have really bad luck, then your server doesn't allow an upload progress bar at all for  cgi scripts

Some servers save the whole post request in a temporary file and start calling the cgi script only when the upload has been completed.
In that case you had to use something like mod_wsgi / mod_python if your server is an apache server.

One known, rather portable  technique is using a 'session-id', Ajax and two cgi scripts:
- your server creates a session id (e.g. cookie) and stores it in a persistent storage (e.g. server side database)
- Your upload script (e/g/ upload.cgi)   will be almost the one, that you currently use. However it will use the unique-id and update an upload counter (e.g. in a data base) for each data chunk, that has been received.
- your upload web page contains a small javascript, which will periodically perform ajax requests to the server (e.g. get_upload_progress.cgi), which will fetch the upload progress from the persistent server storage

Details will depend on the server, that you are using.

Some links worth reading:
- http://stackoverflow.com/questions/4890820/how-to-use-python-cgi-for-file-uploading
-http://development.mumboe.com/?p=11
- http://www.velocityreviews.com/forums/t353548-cgi-module-callback-upload-hook.html

Here a library for the nginx web server:
- http://wiki.nginx.org/HttpUploadProgressModule

And here a wsgi middleware forfile upload progress
- http://code.activestate.com/pypm/gp.fileupload/

Author

Commented:
Thanks, those links put me on the right track