Javascript 使用 Ajax 以一种形式同时上传数据和文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10899384/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 03:29:28  来源:igfitidea点击:

Uploading both data and files in one form using Ajax?

javascriptjqueryajaxforms

提问by Dan

I'm using jQuery and Ajax for my forms to submit data and files but I'm not sure how to send both data and files in one form?

我在表单中使用 jQuery 和 Ajax 来提交数据和文件,但我不确定如何以一种形式同时发送数据和文件?

I currently do almost the same with both methods but the way in which the data is gathered into an array is different, the data uses .serialize();but the files use = new FormData($(this)[0]);

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

Is it possible to combine both methods to be able to upload files and data in one form through Ajax?

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

Data jQuery, Ajax and html

数据 jQuery、Ajax 和 html

$("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>

Files jQuery, Ajax and html

文件 jQuery、Ajax 和 html

$("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>

How can I combine the above so that I can send data and files in one form via Ajax?

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

My aim is to be able to send all of this form in one post with Ajax, is it possible?

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

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

回答by Dan

The problem I had was using the wrong jQuery identifier.

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

You can upload data and fileswith one form using ajax.

可以使用 ajax以一种形式上传数据和文件

PHP + HTML

PHP + HTML

<?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

jQuery + 阿贾克斯

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

Short Version

精简版

$("form#data").submit(function(e) {
    e.preventDefault();
    var formData = new FormData(this);    

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

回答by Roey

another option is to use an iframe and set the form's target to it.

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

you may try this (it uses jQuery):

你可以试试这个(它使用 jQuery):

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

it works well with all browsers, you don't need to serialize or prepare the data. one down side is that you can't monitor the progress.

它适用于所有浏览器,您不需要序列化或准备数据。不利的一面是您无法监控进度。

also, at least for chrome, the request will not appear in the "xhr" tab of the developer tools but under "doc"

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

回答by h_power11

I was having this same issue in ASP.Net MVC with HttpPostedFilebase and instead of using form on Submit I needed to use button on click where I needed to do some stuff and then if all OK the submit form so here is how I got it working

我在带有 HttpPostedFilebase 的 ASP.Net MVC 中遇到了同样的问题,而不是在提交时使用表单,我需要在需要做一些事情的地方使用单击按钮,然后如果一切正常提交表单,这就是我如何让它工作的

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

this will than correctly populate your MVC model, please make sure in your Model, The Property for HttpPostedFileBase[] has the same name as the Nameof the input control in html i.e.

这将比正确填充您的 MVC 模型,请确保在您的模型中,HttpPostedFileBase[] 的属性与html 中的输入控件的名称具有相同的名称,即

<input id="fileupload" type="file" name="UploadedFiles" multiple>

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

回答by schaenk

Or shorter:

或更短:

$("form#data").submit(function() {
    var formData = new FormData(this);
    $.post($(this).attr("action"), formData, function() {
        // success    
    });
    return false;
});

回答by Adithya Upadhya

For me, it didn't work without enctype: 'multipart/form-data'field in the Ajax request. I hope it helps someone who is stuck in a similar problem.

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

Even though the enctypewas already set in the form attribute, for some reason, the Ajax request didn't automatically identify the enctypewithout explicit declaration (jQuery 3.3.1).

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

// 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>

As others mentioned above, please also pay special attention to the contentTypeand processDatafields.

正如上面提到的其他人,还请特别注意contentTypeprocessData字段。

回答by Pranav Kulshrestha

For me following code work

对我来说下面的代码工作

$(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);
});

In your Action Post Method, pass parameter as HttpPostedFileBase UploadFile and make sure your file input has same as mentioned in your parameter of the Action Method. It should work with AJAX Begin form as well.

在您的 Action Post 方法中,将参数作为 HttpPostedFileBase UploadFile 传递,并确保您的文件输入与 Action Method 的参数中提到的相同。它也应该与 AJAX 开始表单一起使用。

Remember over here that your AJAX BEGIN Form will not work over here since you make your post call defined in the code mentioned above and you can reference your method in the code as per the Requirement

请记住,您的 AJAX BEGIN 表单将无法在此处工作,因为您在上面提到的代码中定义了 post 调用,并且您可以根据要求在代码中引用您的方法

I know I am answering late but this is what worked for me

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

回答by ndarriulat

In my case I had to make a POST request, which had information sent through the header, and also a file sent using a FormData object.

在我的情况下,我必须发出一个 POST 请求,其中包含通过标头发送的信息,以及使用 FormData 对象发送的文件。

I made it work using a combination of some of the answers here, so basically what ended up working was having this five lines in my Ajax request:

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

 contentType: "application/octet-stream",
 enctype: 'multipart/form-data',
 contentType: false,
 processData: false,
 data: formData,

Where formData was a variable created like this:

其中 formData 是一个像这样创建的变量:

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

回答by Shailesh Dwivedi

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

<script>
$(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;
});
</script>

///// otherpage.php

///// otherpage.php

<?php
    print_r($_FILES);
?>