The problem
So you’ve got your nice form, and want to allow users to attach a file. If the user tries to upload a file which exceeds the ‘post_max_size’ value in php.ini then WHAMMY…the entire $_POST variable will be empty.
This is a massive headache in terms of UX, your user has just spent 5 minutes entering information and simply because they tried to attach a 4Tb file then all this is lost. Validating the size of the file they attach is not the issue, the issue is that if the upload is part of a form with other text fields then their input will be lost.
The solution
First off, lets get the current value for ‘post_max_size’ and ‘upload_max_filesize’ from php.ini.

upload_max_filesize

post_max_size
As you can see, my post_max_size is 20Mb and my upload_max_filesize is 10Mb.
Why are they different? Well, anything over 10Mb will upload but will return a decent error you can catch, but if a user tries to upload a file over 20Mb then the internet explodes and PHP simply dumps the whole lot, $_POST will be empty, as will $_FILES, $_REQUEST etc.
How this would look to the user uploading 15mb file

How this would look to the user uploading 15mb file
How this would look to the user uploading 25mb file

How this would look to the user uploading 25mb file
As you can see, if post_max_size is exceeded (the second screenshot), all the $_POST data is lost and the user has to start again.
One solution to this would be to have 2 separate forms, or split up the steps in the process so the file upload is on a separate page.
However there is a better solution: Ajax.
This approach uses two separate forms but we do it on the same page in such a way the UX is seamless.
- When the user clicks “Save and Continue” we submit form 1 (just the text/select fields) via ajax as a serialized array
- Validate it on the server and return a JSON array of info (such as: did it validate? if there are errors what are they? etc.)
- If it does validate, save it in a session
- Check the response client side, and if ok we submit form 2 (just the files) the usual way
Here’s how it looks.
The HTML for the forms
The JS (I’m using jQuery)
My code on the server validates the data from the text fields, saves it to a session, and returns a JSON object. If the validation fails it returns something like this.
We can use the response to show errors BEFORE the form with the files is submitted (the normal way).

Validation errors, used a modal because i'm hip
If the response in the JSON is ‘success’ then we simply submit the second form as normal. If the file/s still exceed the post_max_size then at least the previous text input is on the session and can be used to populate the fields again.
How this would look to the user uploading 50mb file

Huge upload, $_POST is lost but we have the text fields in the session