4

In my code there is a single form that contains 2 input elements:

text input and

file input (which will contain an image).

I am appending each file input on button click and want to upload all images in an ajax call, but in my PHP file I only get the final image and value of text input.

My html and jquery code are as follows:

HTML code

<html>
    <body>
        <form name="ajax_image" id="ajax_image" method="post">
            <input type="text" name="project_name" id="project_name" placeholder="Project Name" /><br/><br/>
            <input type="text" name="project_duration" id="project_duration" placeholder="Project Duration" /><br/><br/>
            <div id="image_uploads">
            <input type="file" name="project_image[]" class="project_image" placeholder="Project Image" />
           <input type="button" name="add_upload" id="add_upload" value="+" />
            <br/><br/>
            </div>
            <input type="submit" name="submit"  id="submit" value="Submit" />
        </form>
    </body>
</html>

Jquery code

<script>
    $(document).ready(function () {
       var count=0;
        $("#add_upload").click(function(){ 
            var input = '<input type="file" name="project_image[]" class="project_image" placeholder="Project Image"/><br/><br/>'
                $("#image_uploads").append(input); 
                count++;
            });

        $("#ajax_image").submit(function (event) {                  
            event.preventDefault();          
            var data = new FormData();    


                   for(var j=0 ; j<= count ; j++)
            {
               // alert(j);
            $.each($(".project_image")[j].files, function (i, file)
            {          
                data.append(i, file);
            });
            }            
            $.each($('#ajax_image').serializeArray(), function (i, obj) {
                data.append(obj.name, obj.value)
            });

            $.ajax({
                url: "http://localhost/hetal/multi_image_php_ajax.php",
                type: "POST",
                data: data,
                processData: false,
                contentType: false,
                success: function () {
                    alert('Form Submitted!');
                },
                error: function () {
                    alert("error in ajax form submission");
                }
            });
        });
    });

</script>

PHP file

<?php
print_r($_POST);

print_r($_FILES);
?>
1
  • 1
    Have you used <input type="file" name="project_image[]" class="project_image" placeholder="Project Image" multiple /> to get multiple files? Commented Jun 19, 2015 at 7:12

3 Answers 3

2

After document is ready add a variable:

var fileCounter = 0;

Pass it to the first parameter of the append method, then increment.

$.each($(".project_image")[j].files, function (i, file)
{          
     data.append(fileCounter, file);
     fileCounter++;
});

The problem is that you sent two files with the same name in POST request. You can see this by opening the ajax request and click the POST tab in Firebug. It was something like this for both files, so every next file overrides the previous one:

Content-Disposition: form-data; name="0";

EDIT: It exists a simpler solution just by pass a j as a first parameter of append without a clutter:

for(var j=0 ; j<= count ; j++)
{
    $.each($(".project_image")[j].files, function (i, file)
    { 
         data.append(j, file);
     });
}

EDIT 2

It can also be done by using multiple attribute of a file input. It wouldn't be neccessary then to add other inputs, but just send them in only once.

HTML:

<form name="ajax_image" id="ajax_image" method="post" enctype="multipart/form-data">
        <input type="text" name="project_name" id="project_name" placeholder="Project Name" /><br/><br/>
        <input type="text" name="project_duration" id="project_duration" placeholder="Project Duration" /><br/><br/>
        <input type="file" name="project_images" class="project_images" placeholder="Project Image" multiple /><br/><br/>
        <input type="submit" name="submit"  id="submit" value="Submit" />
    </form>

JS:

$(document).ready(function () {
    $("#ajax_image").submit(function (event) {
        var data = new FormData();

        event.preventDefault();

        $.each($(".project_images")[0].files, function (key, file){
            data.append(key, file);
        });  

        $.each($('#ajax_image').serializeArray(), function (i, obj) {
            data.append(obj.name, obj.value)
        });

        $.ajax({
            url: "upload.php",
            type: "POST",
            data: data,
            processData: false,
            contentType: false,
            success: function () {
                alert('Form Submitted!');
            },
            error: function () {
                alert("error in ajax form submission");
            }
         });
    });
});
Sign up to request clarification or add additional context in comments.

2 Comments

There's already a "fileCounter" in his existing code. var count=0;. Asking him to add another counter is only adding clutter.
Won't the jquery each cancel out the logic of the outer for loop? so j would be the same for every data then it would run many times as count is?
2

The problem appears to be with this part of the JS:

 for(var j=0 ; j<= count ; j++) {
        // alert(j);
        $.each($(".project_image")[j].files, function (i, file)
        {          
            data.append(i, file);
        });
 }

Assume there are 3 files (count == 3). You are looping the $.each call three times. Each time, you are going through file project_image[j] and appending it to the FormData by the key i. Since there is only one project_image[j] for each j, the value of i is always 0.

You end up with data going through this sequence of events:

  • At j = 0, data: {0: [some binary of first image]}
  • At j = 1, data: {0: [some binary of second image]}
  • At j = 2, data: {0: [some binary of third image]}

Note that key 0 is continually being overwritten.

You should edit your code such that:

  1. Obviously, there's no need to call $.each inside the loop. This is the root cause of your confusion - you are confusing the two indices.
  2. Fix the key names, i.e. reference the correct loop index. In short, change your i which is always 0 to j which is actually the index you want.

Comments

0

Rather than creating your code. i recommend you to use Jquery plugins

Like

uploadify

Uploadifive

Jquery file upload

for security reasons you wont be able to upload a file directly with jquery ajax. so its better to use a plugin with more options and more facilities

  • it will help you upload multiple files with loader and progress bar and preview

1 Comment

thanks you all for help me to fine answer. i got my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.