A couple of week's back, a friend of mine asked if there was any way he could send me a file. Not for the site, just a video. So I created a quick form that would allow him to submit a file. Not a problem, in fact a pretty easy task until you find out he wants to send a 1.6Gb file. Still not a problem, you just have to adjust the php.ini file to allow for an upload of this size. Contrary to a lot that I've read, the only changes that need to be made are to the post_max_size and upload_max_filesize variables to allow for a file of this size. (I set them both to 10000M and that seemed to work fine). Quick test and done - works OK so I sent him a link. Next I get a note saying that there's no way to tell if it's working. In other words, you click submit and nothing happens until the file has completed the upload which, with a 1.6Gb file over a home network takes about 12 hours depending on the upload speed of the sender. After assuring him that it was in fact working, even though nothing appeared to be happening, he let it run and I got the file. Still, seemed like a good idea to figure out how to create some kind of progress bar.
This, I find is incredibly difficult. First, this appears to be something that has only recently been made available in PHP (v5.2). As best I understand, the latest version has some hook that you can get information from once an upload starts. Great - I'm on the latest version so this shouldn't be too difficult. PHP has these extensions (called PECL's) that you can install to give additional functionality. A quick look and there's a php_uploadprogress extension so surely you just install it and add the right syntax in your code and we're done. Well, best I can make out from the logs I've visited is that the person who developed the php_uploadprogress extension doesn't have a Windows machine, so it works great on *NIX systems, but the dll file doesn't actually work. It appears to have been fixed by someone else and is ready to be uploaded as a revised version to the PECL library, but doesn't appear to have been done yet. What's more, I found the revised dll file on another site <<<link removed as site no longer exists>>> at lunch, however, when I went to download the file at night, the site was down for 3 days. Thankfully, I finally got access and downloaded the dll and it worked.
Next thing is to code a php file to do all the calculating of the upload. I used 4 files to get this to work as follows:
- upload file form (where the file is submitted from)
- upload file progress (to process the upload once complete)
- upload progress (to display the progress of the upload)
- upload progress bar (used to create the dynamic picture of an increasing bar)
Starting at the beginning, obviously you need a form from which to submit the file. This is pretty easy. The form type must be of type "multipart/form-data" to send a file. The field to attach a file is an input field with a type of "file". You also need to create a hidden field before the file field called "UPLOAD_IDENTIFIER" in order to get the uploadprogress dll to work. You need to create a unique ID for the upload to work. I did this simply by using date+time+random. I'm not expecting a plethora of uploads such that this will not work.
Second step is to pop open a window from which to report the upload progress. Originally I tried to do this using the onclick event with the button which worked fine in Firefox, but not in Internet Explorer. The solution is to use the onsubmit event in the form as this seems to work in both browsers that I have. This window needs to refresh itself every x seconds to get updated information on the progress of the upload. I refresh every second, but you can figure out what works best for you. I used the onload event of the body tag to call the setTimeout function. This has a refresh time of 1 second (1000 milliseconds) and has the simple action to refresh (reload) the window or close it if the upload is complete. You can then use the uploadprogress_get_info() function to retrieve information about the progress of the file upload. Basically, installing the PECL and creating the UPLOAD_IDENTIFIER allows the system to tag upload information that can be fetched and put into an array with the uploadprogress_get_info() function. It provides the following:
- time_start - The time that the upload began.
- time_last - The time that the progress info was last updated.
- speed_average - Average speed.
- speed_last - Last measured speed.
- bytes_uploaded - Number of bytes uploaded so far.
- bytes_total - The value of the Content-Length header sent by the browser.
- files_uploaded - Number of files uploaded so far.
- est_sec - Estimated number of seconds remaining.
The graphic of the bar is created by calling a third file and passing it the variable of where the progress is. So, just calculate the % complete using the bytes_uploaded compared to bytes_total and pass it over. Nothing more complicated than that. (Actually, I did spend a lot of time trying to output a GD file in the upload_progress file, but couldn't figure out how to do it without saving the file and loading it which seemed excessive. If I've missed something here, it would be greatly appreciated). The graphic uses the GD capabilities in PHP so you will need to load the GD PECL. If you don't want to do that, you can just display text based progress.
Finally, the uploaded file is processed. In some places of this site, I do things with the file - normally to re-sample a graphic for display, so I reject files I can't handle.
The only thing missing from this description is that I use cookies (mmmmmm cookies) to store information as to where the upload is. Given that the upload progress disappears once the upload is complete, it is difficult to tell the difference of before the upload has started and once it is complete. As the file upload form is loaded, it creates a cookie with the unique ID that will be used for the file upload (in order to allow multiple uploads). It gives the cookie a value of 0. When the upload progress window is opened, it looks to see if the upload has started (if an info can be received from uploadprogress_get_info()). Once started, it gives the cookie a value of 1. The upload file process sets the cookie value to 2 when it loads as this is when the upload is complete. This is used to close the pop-up window instead of refreshing.
All the files I used including the working dll are in the attached <<<link removed as files are old>>> file. I haven't done anything with the dll file and am not trying to take credit for the work of others, that belongs to the original creator as noted on the
PHP website or the person who updated it on the link provided earlier in this article. It just took me a long time to collect the bits, so I'm making them all available here. In addition to the notes above, these require you to have a directory on your root called "uploadedfiles". You also need a setting in your php.ini file to set the temporary directory for the uploadprogress extension to save files uploadprogress.file.filename_template = [root]:/tmp/%s.txt (note you need to include the %s as this is replaced with the file name of the upload - the unique identifier you created).
The files in the attached zip are the basic working files (they don't have any fancy headers or footers). If you want to have a go and see the upload progress in action,
send me a file (just try and make it interesting). I've obviously added a lot of stuff to the form at the end of the link to match the house style of this site.
A couple of last notes. At times during a big upload, the upload file disappears, so you will jump to 100% complete and then back to whatever the correct % is (one more reason why I had to use cookies). Second, in MSIE, the bar flashes on and off each time it loads.
And finally, if you still have problems, let me know and I'll see if I can help.