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

Dan*_*Dan 359 javascript forms ajax jquery

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

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

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

数据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>
Run Code Online (Sandbox Code Playgroud)

文件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>
Run Code Online (Sandbox Code Playgroud)

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

我的目标是能够使用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>
Run Code Online (Sandbox Code Playgroud)

Dan*_*Dan 438

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

可以使用ajax 上传一个表单的数据和文件.

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>
Run Code Online (Sandbox Code Playgroud)

jQuery + Ajax

$("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
    });
});
Run Code Online (Sandbox Code Playgroud)

精简版

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

    $.post($(this).attr("action"), formData, function(data) {
        alert(data);
    });
});
Run Code Online (Sandbox Code Playgroud)

  • `$(this)[0]`只是`this`的别名,所以`new FormData(this)`就足够了. (32认同)
  • 对于未来的读者:contentType和processData声明很重要.有关详细信息,请参阅[此答案](http://stackoverflow.com/a/12756023/16911). (26认同)
  • 在IE <10的版本中,此解决方案将无法工作,因为FormData是一个HTML5对象,在IE 8或9中不存在. (17认同)
  • 似乎无法检查FormData对象,请参阅[此问题](http://stackoverflow.com/questions/17066875/how-to-inspect-formdata)(对于遇到与我一样无知的人)只是因为Object总是空的. (8认同)
  • 这似乎不需要`async:false`来工作并导致移动(单线程)浏览器阻塞 (5认同)

Roe*_*oey 32

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

你可以尝试这个(它使用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);
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

它适用于所有浏览器,您无需序列化或准备数据.一个缺点是你无法监控进度.

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

  • 虽然它有效,但这不是**Ajax! (5认同)
  • 我只是无法相信为什么这个答案得到-2,我最终使用它,因为我需要传统的浏览器支持 (3认同)

小智 15

或更短:

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

  • 再次,这在IE <10中不起作用 (5认同)

Adi*_*hya 14

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

尽管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>
Run Code Online (Sandbox Code Playgroud)

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


h_p*_*r11 11

我在使用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
        });
    }
});
Run Code Online (Sandbox Code Playgroud)

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

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

public class MyViewModel
{
    public HttpPostedFileBase[] UploadedFiles { get; set; }
}
Run Code Online (Sandbox Code Playgroud)


kar*_*agi 6

一个简单但更有效的方法:
new FormData()本身就像一个容器(或一个袋子)。你可以把所有的 attr 或 file 放在里面。您唯一需要附加的是attribute, file, fileName例如:

let formData = new FormData()
formData.append('input', input.files[0], input.files[0].name)
Run Code Online (Sandbox Code Playgroud)

并在 AJAX 请求中传递它。例如:

    let formData = new FormData()
    var d = $('#fileid')[0].files[0]

    formData.append('fileid', d);
    formData.append('inputname', value);

    $.ajax({
        url: '/yourroute',
        method: 'POST',
        contentType: false,
        processData: false,
        data: formData,
        success: function(res){
            console.log('successfully')
        },
        error: function(){
            console.log('error')
        }
    })
Run Code Online (Sandbox Code Playgroud)

您可以使用 FormData 附加 n 个文件或数据。

并且如果您要从 Script.js 文件到 Node.js 中的路由文件发出 AJAX 请求,请注意使用
req.body访问数据(即文本)
req.files来访问文件(即图像、视频等)