Hey guys, first post here! Thought I'd make it a whopper.

So here is the deal, I have to write a file upload script to plunk into an existing page. The upload is a strait PHP/POST upload. I have one file that handles all the forms, the action just goes to php_self and I sort through it there.

There are basically two forms, then a results page. My one upload.php file handles all three.
The user fills in data for the first form, name, company, how many files they need to upload, etc... When submitted, it goes around to form number 2. This form is dynamically created to give them the number of file input boxes they need. It's a barbaric way to do things, but I'm not being paid much. So...

They browse for the files they need and submit. I create a folder on the server based on their input from the first form, and upload the files there. This all works great. I have a file size filter, a file type filter, and other stuff. But the problem is with PHP's server side file size limitations. That is max post size and max file size.
When the user betrays my client-side file size check, I just show the error and it's good. But when the file is too big for php.ini settings, I cannot for the life of me trap this error. What happens is the page just refreshes, which takes me back to the first form page, not the results page that is supposed to be shown.
I have tried trapping the error in the upload code here:

if (move_uploaded_file($file_tmp,$dir.$file_name)) {
echo "<script>alert('success')</script>";
echo "File $i: ($file_name) Uploaded.<br>";
} else {
die("The file is bigger than this server allows");
}

Never mind the echo, that's just troubleshooting. Also, the code right here has changed about 10 times, I've been putting in every kind of error trap that google will throw at me. The problem is, when the file they input exceeds what PHP allows, the code never seems to get here. It's as if all the file checking never takes place, the page just refreshes back.
I've tried setting my own error handler function, it won't run. I've tried putting DIE statements and javascript popups all through the code to see if even reaches those areas, and it doesn't seem to. After they hit submit, the page loads, and that's it, it just loads, then it goes back to the first form, no errors, no warnings.
Also, when it refreshes back to the first form, there is no post data. I've dumped the $_POST data and it is empty after it does this. However if I hit refresh on the page, it tells me that it has to resubmit data! I don't know what data, since POST is empty!

It is getting aggravating. How can I trap this dumb error? How can I even trouble shoot? It leaves no trails or clues! I've been reading the php manuals, W3C, reading up on file uploads. People tell you how to increase file size limitations in php.ini, they don't tell you how to trap the errors.

So I guess the basic question is I'm wondering how the logic goes from file upload to max file size and max post size. When you try to submit a form with a file that exceeds server limits, what is SUPPOSED to happen? How would somebody normally trap this condition? I know for a fact I have no code to just refresh the page on an error, no code to go back to the first form on error, it is a mystery. So how do I trap the error?

Thanks!

    Hey zackw,

    I think the POST thing may be a server issue. I don't know the internals workings of Apache or PHP that well. In any case, I found something that may help you. You are right, $POST will appear empty if the file uploaded is bigger than the size that's set in php.ini. I think what happens is that PHP refuses to process the POST content if it exceeds it's set limits. However, you can still use $SERVER['CONTENT_LENGTH'] to figure out if this occurred. The only problem is you still don't have any POST data.

    So let's say you have a variable in your form which dictates which step of the process you are in: initial form filling, second screen with the uploads, confirmation page. Let's call this variable $step. On that second upload page, you may set this variable's value in a hidden field: name="step" value="do_upload". In your PHP script you are probably checking to see what to do next:

    $step = $_POST['step'];
    if ($step == "upload_form") {
        // show the upload form
    }
    else if ($step == "do_upload") {
        // process the files user just uploaded
    }
    else {
        // show the initial form where they fill out name, email, etc
    } 
    

    Since a large file upload will cause $_POST to be empty, now your program is stuck. It thinks you are in step one (i.e. the else statement), so it effectively resets and shows you that initial form making the user start all over again.

    To solve this problem, here's one approach. This may not be the most efficient way (maybe someone else has thoughts?), but hopefully you can make it work. Start a session when you show the initial form. In your PHP code, set a session variable "step" and set the value to "upload_form". When the person submits their contact info, your PHP will go to the second step because it realizes a session has been created and that $_SESSION['step'] == "upload_form", and so it will show the upload form the next time around. If you're doing validation on their initial contact info, just reset that step variable in the session and show them the initial form again. Also, remember to save their contact info to the session so you won't lose it and you don't have to pass through the form again.

    When you display the second form (the upload form), before you output that to the browser, set $SESSION['step'] to "do_upload". That way when the form is submitted this time around, the program knows it's going to the do_upload stage WITHOUT having to rely on the POST data. In the do_upload part of your program, do an error check: if $POST is empty and $_SERVER['CONTENT_LENGTH'] is large (you can compare its value against your file size limits), then you know an error has occurred: one of the files was too big and PHP refused to process the POST data. Now you can throw an error back to the user and show the upload form again. Also, since you've saved their initial contact info in their server session, they don't need to enter it again even though your POST data is lost.

    Unfortunately, since the POST data is lost, I don't think you'll be able to accept some of the files. So if they upload 3 files of normal size and a fourth one that's too big, I think they'll have to re-upload everything again.

    -sridhar

      zackw wrote:

      I cannot for the life of me trap this error.

      See: [man]features.file-upload.errors[/man]

      EDIT: Oh yeah; welcome to PHPBuilder! 🙂

        You may both be on to something there.

        I am using Session variables to keep track of things, but my main IF structure may still be using POST. If it's true that a failed upload causes all POST data to disappear, that could explain some things.

        I'll get back here when I fix the script. I'm out of town over next week so hopefully I'll get it resolved.

        Thanks

          A failed upload shouldn't lose any data at all; if the upload was too large, didn't work out well, etc. then PHP will fill in the error variable appropriately. If you're losing all POST data, I would think that's the browser's fault and not PHP's.

            a month later

            Sorry it's been a while.

            I didn't completely end up fixing this problem, but I did find out something interesting.

            When you try to upload a file and it exceeds the upload_max_filesize, the error is trapped quite easily in your code, you can do it perhaps on a " if (!is_uploaded_file) " block. If there was any kind of error with the file, you could catch it there, including max_filesize limits.
            When checking the possible error codes (here), you'll notice that error 1 and 2 have to do with file size. But none of them have to do with POST size limits. Note that all these errors are a ['userfile']['error'] code. They have to do with file uploads, not POST in general.
            Now, the post_max_size is another beast altogether. Exceeding this (I think), would not trigger errors to be set in the ['userfile'] global, since it's a POST issue and not only a file issue.
            On my personal server, I've fiddled with both max_filesize and post_max_size to see which I can trap and when everything dies. Here are some scenarios:

            Assume max file size is 20mb and max post size is 60mb.
            They have 3 file input boxes.

            Box 1 20mb file
            Box 2 20mb file
            Box 3 20mb file
            This will be a success, no errors.

            Box 1 40mb file
            Box 2 20mb file
            Box 3 empty
            This will be a success, I can trap the error that one file is too big, because max post was not reached, this allowed all data to be uploaded.

            Box 1 40mb file
            Box 2 10mb file
            Box 3 15mb file
            Failed! I cannot trap the one file which is too big, because all data together exceeds max post and (I guess) was discarded and POST emptied.

            I have searched Google for days trying to find out specifically how to trap a post_max_size error condition, and have not found the solution yet, it's as if you just can't catch it!

            So what I've done is this:

            I limited the customer form to two uploads at once, rather than letting them choose. I set file size limit to 60mb. Based on what I read, they suggest I should then set my max post to about 124mb, this lets both files upload, plus extra data. However, as you might have guessed, I would never be able to trap a file size error unless both files are under the post limit. Such as one 65mb file and one 20mb file. But if they try to send one 70mb file and one 55mb file, post limit is reached and there is no error trap. So rather than set file limit to 60 and post to 124mb, I set file limit to 60 and post to something like 200mb. This allows an extra 80mb buffer in case they upload large files. So when they try to send a 70mb file and a 55mb file, the 70 can be rejected and the 55 can be allowed because together they are 125mb and haven't reached post limits. So at least the 55mb file can be uploaded.

            It's a pretty dirty way to do things, but without moving to commercial software, activex controls, security keys and so forth, client-size file size checking is difficult. This seems to be the only way to do it. I did not yet try to check what is in ['CONTENT_LENGTH'] but I'm assuming it will be a grand total, not individual file sizes. So if they upload 2 or 3 files, I wouldn't know which is too big, and all 3 would still be rejected. By making post size very large, I leave enough buffer to be able to upload all files and just reject the large ones. If somebody tries to go hog wild and upload a 300mb file and they have to wait for 2 hours and get rejected back to a blank form, I'm not too worried about it.

            So unless somebody can specifically capture post size limit errors, I couldn't find it.

            Thanks!

              Write a Reply...