No error when submitting without ajax on form but error when ajax is used.

Hi all,

I am having problems submitting a form via ajax where without ajax it submits without any problems.

If I use this on it's own the image uploads correctly:

<form id="edit_image1_form" action="upload_file.php" method="post" enctype="multipart/form-data">
    <img id="edit_image1" src="<?php echo $venue_image_upload_one; ?>" alt="" />
    <input type="file" name="file" id="file" onchange="readURL1(this);" style="width:155px;"><br>
    <input type="submit" id="upload_image1_submit" name="upload_image1_submit" value="Update Image">
</form>

Open in new window


I am having problems submitting a form via ajax where without ajax it submits without any problems.

If I use this on it's own the image uploads correctly:

<form id="edit_image1_form" action="upload_file.php" method="post" enctype="multipart/form-data">
    <img id="edit_image1" src="<?php echo $venue_image_upload_one; ?>" alt="" />
    <input type="file" name="file" id="file" onchange="readURL1(this);" style="width:155px;"><br>
    <input type="submit" id="upload_image1_submit" name="upload_image1_submit" value="Update Image">
</form>

Open in new window


But when I add this it give me an error and not upload is done:

$("#upload_image1_submit").click(function() {

        var url = "upload_file.php"; 

        $.ajax({
               type: "POST",
               url: url,
               data: $("#edit_image1_form").serialize(), //form name here
               success: function(data)
               {
                  alert(data); 

               }
             });

            return false; 
        });

Open in new window


The error is Invalid File from here:

<?php
    $allowedExts = array("gif", "jpeg", "jpg", "png");
    $temp = explode(".", $_FILES["file"]["name"]);
    $extension = end($temp);

    if ((($_FILES["file"]["type"] == "image/gif")
    || ($_FILES["file"]["type"] == "image/jpeg")
    || ($_FILES["file"]["type"] == "image/jpg")
    || ($_FILES["file"]["type"] == "image/pjpeg")
    || ($_FILES["file"]["type"] == "image/x-png")
    || ($_FILES["file"]["type"] == "image/png"))
    && ($_FILES["file"]["size"] < 20000)
    && in_array($extension, $allowedExts))
      {

      if ($_FILES["file"]["error"] > 0)
        {
        echo "Return Code: " . $_FILES["file"]["error"] . "<br>";
        }
      else
        {
        echo "Upload: " . $_FILES["file"]["name"] . "<br>";
        echo "Type: " . $_FILES["file"]["type"] . "<br>";
        echo "Size: " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
        echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br>";

        if (file_exists("upload/" . $_FILES["file"]["name"]))
          {
          echo $_FILES["file"]["name"] . " already exists. ";
          }
        else
          {
          move_uploaded_file($_FILES["file"]["tmp_name"],
          "upload/" . $_FILES["file"]["name"]);
          echo "Stored in: " . "upload/" . $_FILES["file"]["name"];
          }
        }
      }
    else
      {
      echo "Invalid file"; //HERE
      }
?>

Open in new window


BUT my problem is that if I submit the form without ajax I will not get this error and the image I'm uploading all the time for testing is the same one.

Any ideas on what this could be and how I could fix it?
LVL 1
error2013Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Ray PaseurCommented:
It appears that this if() collection is somehow violated and that triggers the "invalid file" message.

    if ((($_FILES["file"]["type"] == "image/gif")
    || ($_FILES["file"]["type"] == "image/jpeg")
    || ($_FILES["file"]["type"] == "image/jpg")
    || ($_FILES["file"]["type"] == "image/pjpeg")
    || ($_FILES["file"]["type"] == "image/x-png")
    || ($_FILES["file"]["type"] == "image/png"))
    && ($_FILES["file"]["size"] < 20000)
    && in_array($extension, $allowedExts))
    {

Open in new window

To my way of thinking, that's too many conditions to test for with one statement.  You might consider isolating the tests or using in_array() for $_FILES["file"]["type"].

You might want to use var_dump($_FILES) and var_dump($_POST) to see what you're getting for input.  With the AJAX in play, the var_dump() output might need to be written to disk.  You might be able to use output buffering and error_log() to get the information somewhere that you can see it.
0
error2013Author Commented:
Hi Ray ...

The thing is that I do not get this error when I submit without Ajax
0
Ray PaseurCommented:
Yes, I get that part.  I want to see what is getting submitted - to compare the submits in the two different cases.

Where is "ReadURL1" that is called by onChange() ?
0
Cloud Class® Course: C++ 11 Fundamentals

This course will introduce you to C++ 11 and teach you about syntax fundamentals.

Ray PaseurCommented:
Try using this for the action script.

<?php
error_reporting(E_ALL);
ob_start();
echo '<pre>' . PHP_EOL;
echo 'POST: ' . PHP_EOL;
var_dump($_POST);
echo 'FILES: ' . PHP_EOL;
var_dump($_FILES);
$msg = ob_get_clean();
error_log($msg);

Open in new window

This is the sort of thing you would expect to find in the error log, from my test without AJAX.

[20-Sep-2013 08:11:31 America/Chicago] <pre>
POST: 
array(1) {
  ["upload_image1_submit"]=>
  string(12) "Update Image"
}
FILES: 
array(1) {
  ["file"]=>
  array(5) {
    ["name"]=>
    string(23) "83_gray_frugal_mule.png"
    ["type"]=>
    string(9) "image/png"
    ["tmp_name"]=>
    string(14) "/tmp/php8wK0B8"
    ["error"]=>
    int(0)
    ["size"]=>
    int(8840)
  }
}

Open in new window

0
Ray PaseurCommented:
Using this script...

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<script>
$("#upload_image1_submit").click(function() {

        var url = "RAY_temp_error_log.php";

        $.ajax({
               type: "POST",
               url: url,
               data: $("#edit_image1_form").serialize(), //form name here
               success: function(data)
               {
                  alert(data);

               }
             });

            return false;
        });
</script>

<form id="edit_image1_form" action="RAY_temp_error_log.php" method="post" enctype="multipart/form-data">
    <!-- img id="edit_image1" src="<?php echo $venue_image_upload_one; ?>" alt="" /> -->
    <input type="file" name="file" id="file" onchange="readURL1(this);" style="width:155px;"><br>
    <input type="submit" id="upload_image1_submit" name="upload_image1_submit" value="Update Image">
</form>

Open in new window

I got this in the log file:

[20-Sep-2013 08:18:13 America/Chicago] <pre>
POST: 
array(1) {
  ["upload_image1_submit"]=>
  string(12) "Update Image"
}
FILES: 
array(1) {
  ["file"]=>
  array(5) {
    ["name"]=>
    string(23) "83_gray_frugal_mule.png"
    ["type"]=>
    string(9) "image/png"
    ["tmp_name"]=>
    string(14) "/tmp/php4rBhwl"
    ["error"]=>
    int(0)
    ["size"]=>
    int(8840)
  }
}

Open in new window

That suggests to me that the AJAX might not be the source of the problem, since both the static script and the AJAX script seem to send the same data (at least it looks the same to me at first sight).
0
error2013Author Commented:
So I replace the code in the php with this:

<?php
error_reporting(E_ALL);
ob_start();
echo '<pre>' . PHP_EOL;
echo 'POST: ' . PHP_EOL;
var_dump($_POST);
echo 'FILES: ' . PHP_EOL;
var_dump($_FILES);
$msg = ob_get_clean();
error_log($msg);

?
0
error2013Author Commented:
I've tried that and the log on POST is totally empty :o/
0
Ray PaseurCommented:
Here is what I get (identical output whether with or without AJAX) from running the action script.

Upload: 83_gray_frugal_mule.png
Type: image/png
Size: 8.6328125 kB
Temp file: /tmp/phpS6QCe6

Warning: move_uploaded_file(upload/83_gray_frugal_mule.png) [function.move-uploaded-file]: failed to open stream: No such file or directory in /home/websitet/public_html/RAY_temp_error2013_action.php on line 36

Warning: move_uploaded_file() [function.move-uploaded-file]: Unable to move '/tmp/phpS6QCe6' to 'upload/83_gray_frugal_mule.png' in /home/websitet/public_html/RAY_temp_error2013_action.php on line 36
Stored in: upload/83_gray_frugal_mule.png

Open in new window

And that kind of makes sense, because I do not have a directory named "upload" so I will try with a different directory.

Any chance this could be violated?  20,000 is awfully small for image files.

$_FILES["file"]["size"] < 20000
0
Ray PaseurCommented:
log on POST is totally empty :o/
Check your settings for error logging.  You want it on, and probably pointed to a file named error_log
0
Ray PaseurCommented:
Repeated both tests with and without AJAX, but using a good directory on my server for the target of move_uploaded_file().  No trouble found, did not fail.

Then I tried a large image:  "Invalid file"
0
error2013Author Commented:
No, it can't be the file as I'm using a small image for the testing
0
error2013Author Commented:
Here is the image I'm trying to upload
400.png
0
Ray PaseurCommented:
Well, we need to look somewhere else.  The source of the error is not in any of the code posted here.  The only failure I could create (once I got the file paths right) was with an oversize or wrong type of file.
0
error2013Author Commented:
On my way home...I'll try the code totally separate from project code and let you know the result.
0
Chris StanyonWebDevCommented:
You can't send the multipart data through an AJAX request, so you can't use ajax() to upload a file. Trying to do so will submit an empty $_FILES array, as you're finding out. The reason you also got the completely empty $_POST array is that there is nothing else in the form to submit.

The easiest way to achieve this is to use a plugin. I've used Uploadify a few times successfully - http://www.uploadify.com/

@ray - running your code never fires the ajax function - missing document.ready() block
0
error2013Author Commented:
Hi ChrisStanyon,

I hate upload plugins, is there an way of modifying my existing code so it works?
0
Chris StanyonWebDevCommented:
No. It can't be done with AJAX. That's just the way it is.

Actually with HTML5 it can 'sort of' be done, but browser support is very limited. The most effective and robust solution is to use a plug-in - the the hard work's been done for you.

Any particular reason why you hate plug-ins. Unless you want to do something extraordinary, then you simply copy some files, and add a couple of lines of jQuery

$('#file_upload').uploadify({
   'swf'      : 'uploadify.swf',
   'uploader' : 'uploadify.php'
   // Put your options here
});

Open in new window

You can probably use less lines that your current set up!
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
error2013Author Commented:
im actually using html5.
The reason I dont want plugins for this is that I want to have full control of what the code is done as like to keep pages as fast as possible too
0
error2013Author Commented:
ps: in this case browser support is not an issue
0
Ray PaseurCommented:
@ChrisStanyon: I think we never got an empty $_FILES array (at least I never did when testing with the exact script posted in the question).  Whether or not the non-functional AJAX script was in there, the submit was going through to the action script.

@error2013: I think ChrisStanyon's almost certainly right about the AJAX submit.  I know for certain that there is no way to prepopulate the input type="file" control.  It would be a great security hole if you could do this, in effect causing the server to be able to control the client machine and copy any information it wanted if you simply visited a page that could do that.

Why not just do it with plain old HTML forms and submits?  We already know that works.
0
Chris StanyonWebDevCommented:
@error2013 - there's some pretty slick plug-ins available, that are quick. The bottom line here is that you use a script that has been tried and tested to the limits, or you try and fashion your own script that may or may not work in all the browsers.

I understand what you're saying - it's nice to know exactly what's going on in your scripts, but sometimes you have to ask yourself - why re-invent the wheel?

This is one of those times. If you want to upload files asynchronously, then a jQuery plug-in is absolutely the way to go.

@Ray - with the missing (document).ready block, I could never get the ajax() call to fire, so the form data was always POSTed directly. This never resulted in an empty $_FILES array (although without selecting a file the values were empty). If I added the document.ready block, the ajax() call fired, but would always result in an empty $_FILES array being passed to the script. This makes sense, otherwise, as you pointed out, there would be a huge security hole in the browser ;)
0
Ray PaseurCommented:
Yeah, I think the plug-in makes sense, too.  Especially if you don't want to just use the built-in HTML form.  You can get rather exotic with Flash uploaders, etc., but it may not be worth the effort.  

Sidebar note:  I uploaded a bunch of pictures of a car I'm selling to CraigsList.  The upload took a variable number of selected files and seemed very sensible to me.  You might look at how they do it and do some copy/paste.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.