关于javascript:使用Ajax以一种形式上传数据和文件?

Uploading both data and files in one form using Ajax?

我使用jquery和ajax来提交表单中的数据和文件,但我不确定如何在一个表单中同时发送数据和文件?

我目前对这两种方法做的几乎相同,但将数据收集到数组中的方式不同,数据使用.serialize();,而文件使用= new FormData($(this)[0]);

是否可以将这两种方法结合起来,以便通过Ajax以一种形式上载文件和数据?

数据jquery、ajax和html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$("form#data").submit(function(){

    var formData = $(this).serialize();

    $.ajax({
        url: window.location.pathname,
        type: 'POST',
        data: formData,
        async: false,
        success: function (data) {
            alert(data)
        },
        cache: false,
        contentType: false,
        processData: false
    });

    return false;
});

<form id="data" method="post">
    <input type="text" name="first" value="Bob" />
    <input type="text" name="middle" value="James" />
    <input type="text" name="last" value="Smith" />
    <button>Submit</button>
</form>

文件jquery、ajax和html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$("form#files").submit(function(){

    var formData = new FormData($(this)[0]);

    $.ajax({
        url: window.location.pathname,
        type: 'POST',
        data: formData,
        async: false,
        success: function (data) {
            alert(data)
        },
        cache: false,
        contentType: false,
        processData: false
    });

    return false;
});

<form id="files" method="post" enctype="multipart/form-data">
    <input name="image" type="file" />
    <button>Submit</button>
</form>

如何将上述内容结合起来,以便通过Ajax以一种形式发送数据和文件?

我的目标是能够用Ajax将所有这些表单都发送到一个帖子中,这是可能的吗?

1
2
3
4
5
6
7
<form id="datafiles" method="post" enctype="multipart/form-data">
    <input type="text" name="first" value="Bob" />
    <input type="text" name="middle" value="James" />
    <input type="text" name="last" value="Smith" />
    <input name="image" type="file" />
    <button>Submit</button>
</form>


我遇到的问题是使用了错误的jquery标识符。

您可以使用Ajax通过一个表单上传数据和文件。

PHP+HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php

print_r($_POST);
print_r($_FILES);
?>

<form id="data" method="post" enctype="multipart/form-data">
    <input type="text" name="first" value="Bob" />
    <input type="text" name="middle" value="James" />
    <input type="text" name="last" value="Smith" />
    <input name="image" type="file" />
    <button>Submit</button>
</form>

jquery+ajax

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$("form#data").submit(function(e) {
    e.preventDefault();    
    var formData = new FormData(this);

    $.ajax({
        url: window.location.pathname,
        type: 'POST',
        data: formData,
        success: function (data) {
            alert(data)
        },
        cache: false,
        contentType: false,
        processData: false
    });
});

短版

1
2
3
4
5
6
7
8
$("form#data").submit(function(e) {
    e.preventDefault();
    var formData = new FormData(this);    

    $.post($(this).attr("action"), formData, function(data) {
        alert(data);
    });
});


另一个选项是使用iframe并将表单的目标设置为它。

您可以尝试此操作(它使用jquery):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function ajax_form($form, on_complete)
{
    var iframe;

    if (!$form.attr('target'))
    {
        //create a unique iframe for the form
        iframe = $("<iframe></iframe>").attr('name', 'ajax_form_' + Math.floor(Math.random() * 999999)).hide().appendTo($('body'));
        $form.attr('target', iframe.attr('name'));
    }

    if (on_complete)
    {
        iframe = iframe || $('iframe[name="' + $form.attr('target') + '"]');
        iframe.load(function ()
        {
            //get the server response
            var response = iframe.contents().find('body').text();
            on_complete(response);
        });
    }
}

它适用于所有浏览器,不需要序列化或准备数据。一方面是你不能监视进度。

另外,至少对于chrome,请求不会出现在开发人员工具的"xhr"选项卡中,而是出现在"doc"下。


或更短:

1
2
3
4
5
6
7
$("form#data").submit(function() {
    var formData = new FormData(this);
    $.post($(this).attr("action"), formData, function() {
        // success    
    });
    return false;
});


我在ASP.NET MVC中遇到了同样的问题,HTTPPostedFileBase,我不使用提交时的表单,而是使用单击需要执行某些操作的位置上的按钮,然后,如果一切正常,则提交表单就是这样工作的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$(".submitbtn").on("click", function(e) {

    var form = $("#Form");

    // you can't pass Jquery form it has to be javascript form object
    var formData = new FormData(form[0]);

    //if you only need to upload files then
    //Grab the File upload control and append each file manually to FormData
    //var files = form.find("#fileupload")[0].files;

    //$.each(files, function() {
    //  var file = $(this);
    //  formData.append(file[0].name, file[0]);
    //});

    if ($(form).valid()) {
        $.ajax({
            type:"POST",
            url: $(form).prop("action"),
            //dataType: 'json', //not sure but works for me without this
            data: formData,
            contentType: false, //this is requireded please see answers above
            processData: false, //this is requireded please see answers above
            //cache: false, //not sure but works for me without this
            error   : ErrorHandler,
            success : successHandler
        });
    }
});

这将无法正确填充您的MVC模型,请确保在您的模型中,httpPostedFileBase[]的属性与HTML中输入控件的名称同名,即。

1
2
3
4
5
6
<input id="fileupload" type="file" name="UploadedFiles" multiple>

public class MyViewModel
{
    public HttpPostedFileBase[] UploadedFiles { get; set; }
}


对于我来说,在Ajax请求中没有enctype: 'multipart/form-data'字段是不起作用的。我希望它能帮助陷入类似问题的人。

尽管在表单属性中已经设置了enctype,但由于某种原因,在没有显式声明(jquery 3.3.1)的情况下,Ajax请求没有自动识别enctype

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Tested, this works for me (jQuery 3.3.1)

fileUploadForm.submit(function (e) {  
    e.preventDefault();
    $.ajax({
            type: 'POST',
            url: $(this).attr('action'),
            enctype: 'multipart/form-data',
            data: new FormData(this),
            processData: false,
            contentType: false,
            success: function (data) {
                console.log('Thank God it worked!');
            }
        }
    );
});

// enctype field was set in the form but Ajax request didn't set it by default.

<form action="process/file-upload" enctype="multipart/form-data" method="post">

     <input type="file" name="input-file" accept="text/plain" required>
     ...
</form>

如上所述,请特别注意contentTypeprocessData字段。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   <form id="form" method="post" action="otherpage.php" enctype="multipart/form-data">
    <input type="text" name="first" value="Bob" />
    <input type="text" name="middle" value="James" />
    <input type="text" name="last" value="Smith" />
    <input name="image" type="file" />
    <button type='button' id='submit_btn'>Submit</button>
</form>


 $(document).on("click","#submit_btn",function(e){  
     //Prevent Instant Click  
    e.preventDefault();
    // Create an FormData object
        var formData =$("#form").submit(function(e){
            return ;
        });
      //formData[0] contain form data only
      // You can directly make object via using form id but it require all ajax operation inside $("form").submit(<!-- Ajax Here   -->)
        var formData = new FormData(formData[0]);    
        $.ajax({
            url: $('#form').attr('action'),
            type: 'POST',
            data: formData,
            success: function(response) {console.log(response);},
            contentType: false,
            processData: false,
            cache: false
        });
        return false;
            });

/////其他页面.php

1
2
3
<?php
print_r($_FILES);
?>


对于我来说,遵循代码工作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  $(function () {
    debugger;
    document.getElementById("FormId").addEventListener("submit", function (e) {
        debugger;
        if (ValidDateFrom()) { // Check Validation
            var form = e.target;
            if (form.getAttribute("enctype") ==="multipart/form-data") {
                debugger;
                if (form.dataset.ajax) {
                    e.preventDefault();
                    e.stopImmediatePropagation();
                    var xhr = new XMLHttpRequest();
                    xhr.open(form.method, form.action);
                    xhr.onreadystatechange = function (result) {
                        debugger;
                        if (xhr.readyState == 4 && xhr.status == 200) {
                            debugger;
                            var responseData = JSON.parse(xhr.responseText);
                            SuccessMethod(responseData); // Redirect to your Success method
                        }
                    };
                    xhr.send(new FormData(form));
                }
            }
        }
    }, true);
});

在action post方法中,将参数传递为httppostedfilebase uploadfile,并确保您的文件输入与action方法的参数中提到的相同。它还应该与Ajax begin表单一起工作。

请记住,Ajax Begin表单在这里不起作用,因为您在上面提到的代码中定义了post调用,并且您可以根据需要在代码中引用您的方法。

我知道我回答得很晚,但这对我很有用


在我的例子中,我必须发出一个post请求,其中包含通过头部发送的信息,以及使用formdata对象发送的文件。

我在这里使用了一些答案的组合,所以基本上最终的工作是在Ajax请求中使用这五行:

1
2
3
4
5
 contentType:"application/octet-stream",
 enctype: 'multipart/form-data',
 contentType: false,
 processData: false,
 data: formData,

其中formdata是这样创建的变量:

1
2
3
4
 var file = document.getElementById('uploadedFile').files[0];
 var form = $('form')[0];
 var formData = new FormData(form);
 formData.append("File", file);