使用Ajax和jQuery上传多个文件

4

我的代码中有一个包含两个输入元素的表单:

文本输入框

文件输入框(其中将包含一张图片)。

我在按钮点击时附加每个文件输入框并希望在ajax调用中上传所有图像, 但是在我的PHP文件中,我只得到了最终图片和文本输入框的值。

我的HTML和jQuery代码如下:

HTML代码

<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 代码

<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文件

<?php
print_r($_POST);

print_r($_FILES);
?>

1
你是否使用过<input type="file" name="project_image[]" class="project_image" placeholder="Project Image" multiple />来获取多个文件? - Varun
3个回答

2
这个问题似乎出现在JS的这一部分:
 for(var j=0 ; j<= count ; j++) {
        // alert(j);
        $.each($(".project_image")[j].files, function (i, file)
        {          
            data.append(i, file);
        });
 }

假设有三个文件(count == 3)。您正在循环执行三次$.each调用。每次,您都会遍历文件project_image[j],并将其附加到FormData中的键i。由于每个j只有一个project_image[j],因此i的值始终为0
您最终得到的data会按照以下事件序列进行处理:
  • j = 0时,data: {0: [第一张图片的二进制数据]}
  • j = 1时,data: {0: [第二张图片的二进制数据]}
  • j = 2时,data: {0: [第三张图片的二进制数据]}
请注意,键0不断被覆盖。
您应该编辑您的代码,使之满足以下要求:
  1. 显然,在循环内部不需要调用$.each。这是您困惑的根本原因——您混淆了两个索引。
  2. 修复键名,即引用正确的循环索引。简而言之,将始终为0的i更改为实际上您想要的索引j

2
文档准备就绪后,添加一个变量:
var fileCounter = 0;

将其传递给append方法的第一个参数,然后递增。

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

问题在于您在POST请求中发送了两个相同名称的文件。您可以通过打开Firebug中的ajax请求并单击POST选项卡来查看这一点。对于两个文件,它们看起来都是这样的,因此每个后续文件都会覆盖前一个文件。
Content-Disposition: form-data; name="0";

今日免费次数已满, 请开通会员/明日再来
for(var j=0 ; j<= count ; j++)
{
    $.each($(".project_image")[j].files, function (i, file)
    { 
         data.append(j, file);
     });
}

编辑2

还可以使用文件输入的multiple属性来完成。这样就不需要添加其他输入了,只需一次发送它们即可。

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");
            }
         });
    });
});

他现有的代码中已经有一个“fileCounter”了。var count=0;。要求他再添加另一个计数器只会增加混乱。 - light
jQuery的each不会取消外部for循环的逻辑吗?所以j对于每个数据来说都是相同的,那么它会运行多次,就像count一样? - Sarfaraaz

0

我建议您使用JQuery插件而不是创建代码。

比如:

Uploadify

Uploadifive

jQuery文件上传

出于安全考虑,您无法直接使用JQuery AJAX上传文件。因此最好使用具有更多选项和更多功能的插件。

  • 它将帮助您上传带有加载器、进度条和预览的多个文件。

谢谢大家帮我找到答案。我已经得到了答案。 - user4976500

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接