After I released uploadprogress 1.0.0 some days ago and finally declared it as stable, it’s time to write that blogpost about some of the limitations and caveats one has to know.
A great help for testing if the extension works, are the demo files. Put them into a directory on your server and see, what it says. I tried to make the error messages as clear as possible.
Call to undefined function uploadprogress_get_info()
If you get the above message, the extension wasn’t properly installed. Make sure, you restart your webserver after you installed the extension and that it shows up in phpinfo() and there’s an entry like this:
Also check, if the uploadprogress.so really ended up in your “extension_dir” (check that path in phpinfo()) or if you’re using windows php_uploadprogress.dll
Running it on other modules than mod_php on Apache ( like fastcgi)
Unfortunately I only could get the extension running with mod_php on an Apache httpd. I tried with fastcgi, but somehow the hooks didn’t get called and I wasn’t able to investigate further. There’s this bug for that issue, if you have anything useful to add, there’s the place :)
Running on a Windows Server
Problems with Suhosin
The suhosin extension had a bug which prevented the uploadprogress from working properly. This bug was fixed in Suhosin 0.9.26 last August.
Please make sure that the path configured in uploadprogress.file.filename_template is set to something, which is writeable for the webserver. I tried to autodetect your temporary folder more accurately than just assume it’s /tmp/ if not properly set. But at the end it was more complicated than I thought and not worth the trouble, as it has only to be set once.
Running on something < PHP 5.2
This is not possible, since the extension relies on some hooks/callbacks only introduced with PHP 5.2.0
Checking if files are too big
I often get asked if it’s possible to abort the upload, if a file is too large. Here’s the hopefully not too long answer:
There are 2 php.ini settings responsible for deciding what’s “too large”.
upload_max_filesize defines the max allowed size of one file. If you have more than one file upload field, each file can have this max size. It is by default 2MB.
post_max_size defines the size the whole post is allowed to take, including all your text-fields and all your file fields. This is 8MB by default and should be larger than upload_max_filesize to make sense.
Now, depending on what limit the post hits, different things happen. If the total post size is larger than post_max_size, then PHP aborts the upload just right at the beginning and never informs the extension about that. The whole upload happens nevertheless, there’s just no data available to PHP at the end. We can’t change that in the extension, there’s never any data coming to the extension. Your only way to handle this is to check on the client side, if no data is getting through to the extension after some time and then inform the user about the fact, that his file may be too large.
On the other hand, if the whole post is smaller than post_max_size but a file is larger than upload_max_filesize you have a chance. The data is getting through to the extension and you can get the current info with uploadprogress_get_info(), for example the size of the file. If that size is larger than upload_max_filesize, you can inform your user, that it’s too large and his upload is futile. The example handles that case with a message. With some client side trickery (eg. reload the upload iframe) you could even abort the upload.
The position and content of UPLOAD_IDENTIFIER within the form is important
The UPLOAD_IDENTIFIER field in your upload form is very important. Without this field, it won’t work properly. Furthermore, the field has to be before the file upload fields in the form. The way it works on the server side is asking for that order.
And make sure the UPLOAD_IDENTIFIER value is unique to the form and is not used anywhere else. If you use it twice for different (simultanous) uploads, the values will be wrong. It’s also better to not use the session-id for this, since if a user uploads two different files in two different forms, the result will be undefined. Something like md5(session_id() . microtime()) should be enough.
The function only returns NULL
First, make sure that the ID used for uploadprogress_get_info() is really the same as specified in UPLOAD_IDENTIFIER. If they are different, it doesn’t work.
Second, if your upload only takes a short time, there may be just no data at the moment you asked for them. Either search for a slow connection, use a huge file (and make sure the ini settings allow such huge uploads) or use something like Charles for throtteling your connection.
Why can’t the extension tell, when an upload is finished?
As you may have realized, when an upload is finished, the extension just returns NULL, as if an upload never happened. This is because the temporary upload data is deleted as soon as the upload is finished. The reason for that is, that we have no other point in time, when we could do that reliably. We could add a function to delete the data manually, but if you forget that (or for any reason never come to that point), you’re disk will gradually fill up with this data.
Another way would be to add something like the session garbage collection to clean old data from time to time. That would be technically possible, as far as I can see.
On the other hand, a useful upload progress is doable without the “it really has finished” info, as the example shows :)
Why not use $_SESSION for the info?
I didn’t dig very deep into that but the way an upload is handled, this is not easily doable. I doubt that a session can already be initialized during an upload. As far as I could see, that’s not the case. Furthermore, the upload and the reading are 2 simultaneous processes, which can lead to problems regarding sessions. But I’d be happy to be proven otherwise :)
It segfaults, when I don’t include UPLOAD_IDENTIFIER
You use a very very very old version of the extension, please upgrade as soon as possible.
Is it stable?
With the 1.0.0 release I declared it as stable, to make those sysadmins happy, which only install stuff marked as stable. So yes, it is now stable :)