File uploads via HTTP are an annoyance. Web Browser know quite a lot but still the give little feedback to the users. Some a bit more, most close to no feedback. Now over the years this led to man unhappy users. Over the last year, with all these AJAX things, solutions emerged so that one can periodically poll the web server on a second connection for the status. For implementing this we have one architectural problem: PHP implements, for very good reasons, a shared nothing architecture. So one request from connection has no insight into another request/connection - but this is needed for the upload progress. Different people thought about this and implemented solutions. One of the first things was implemented in APC, another one by a special uploadprogress extension. They are nice and found quite some adoption but they have two problems. For one they are not fully native to PHP, so they have to be installed additionally, and the use a local storage to transport the status. APC uses the system's shared memory. upload_progress the filesystem (yes, file systems could be shared, I do know that). not very satisfying for having PHP as the language for solving the web problem.
The obvious solution, of course, would be to use PHP's session handling system for this. The PHP session system is an integral part of PHP and can be configured to use different storage handlers, like the local file system or memcache, which can be useful to share session data in a load-balanced cluster. Now there were some technical issues why this wasn't done at first ... but then Arnaud Le Blanc sat down and created a proper implementation of an upload progress storage handler which has been commit to PHP trunk.
Long story short: In the next version of PHP (5.4?) you will, mot likely, have an Upload Progress mechanism built-in.
Arnaud wrote a nice RFC explaining this functionality. So we configure our PHP to enable this feature, by making sure we have the default values:
session.upload_progress.enabled = 1
session.upload_progress.prefix = upload_progress_
session.upload_progress.name = PHP_SESSION_UPLOAD_PROGRESS
And we are set to go. Then we obviously need an HTML file upload form:
<form action="upload.php" method="POST" enctype="multipart/form-data">
<input type="hidden" name="<?php echo ini_get("session.upload_progress.name"); ?>" value="johannesupload" />
<input type="file" name="file1" />
<input type="file" name="file2" />
<input type="submit" />
</form>
And we can upload a file. If the file is big enough (and the connection slow enough) we can then periodically poll the server and read and read data about the progress from the $_SESSION["upload_progress_johannesupload"] variable. The full contents is mentioned in the RFC, so I won't quote it here.
So far so good. But how to poll? Well, take the sample by Rasmus about the above mentioned APC-based solution and adopt it. I let this to the experienced reader as exercise 
Disclaimer: This article is describing features in not released software. Things may change without notice till it is release. Feel free to read other blog postings from my series of new features!
P.S. I still think the browser should give better feedback by itself. As should it offer better integration of HTTP-Auth, like a simple logout button ...
Friday, December 3. 2010 at 22:16 (Link) (Reply)
But I agree, this should have been supported by browsers since ages.
Friday, December 3. 2010 at 22:40 (Reply)
I'd love that, too, but ironically, that would mean we wouldn't need sessions anymore, and then the solution that's you outlined above would be useless
Friday, December 3. 2010 at 23:15 (Link) (Reply)
Johannes, do you know if there are plans to hide away the underlying implementation with a comparable set of functions?
The current API feels a little immature, what with ini_get call and session calls...
Messy.
Saturday, December 4. 2010 at 09:37 (Link) (Reply)
Saturday, December 4. 2010 at 16:06 (Reply)
Sunday, December 5. 2010 at 10:59 (Link) (Reply)
Einziger Nachteil dabei: der Status-Poll muss auf dem selben nginx landen wie der Upload, das kann nachteilig sein wenn man mehrere nginx Server nebeneinander betreibt.
Für die Mehrheit, die keinen Reverse-Proxy mit einem solchen Feature betreibt ist die PHP-Session-Lösung ein sehr schönes Feature!
Sunday, December 5. 2010 at 11:02 (Link) (Reply)
I will use my nginx to poll the status of an upload, then I don't need a PHP process for that.
One drawback: The status poll has to target the same nginx server as the form upload, if you have more than 1 nginx that can be a problem.
The majority has no reverse proxy and will be happy about this new feature!
Tuesday, December 7. 2010 at 05:18 (Link) (Reply)
One thing to note, I've noticed Chrome already shows upload progress (at least, how smart the client is) in the status bar. I thought that was kind of neat. Might not be per-file or anything cool but it gives -some- idea of how many bytes it's sent out.
Tuesday, December 7. 2010 at 05:24 (Link) (Reply)
Now to talk someone into getting it into 5.3
Saturday, April 30. 2011 at 00:46 (Reply)