Javascript 如何在 jQuery 中使用 Ajax 请求发送 FormData 对象?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6974684/
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 00:04:19  来源:igfitidea点击:

How to send FormData objects with Ajax-requests in jQuery?

javascriptjqueryajaxhtmlmultipartform-data

提问by ?ime Vidas

The XMLHttpRequest Level 2standard (still a working draft) defines the FormDatainterface. This interface enables appending Fileobjects to XHR-requests (Ajax-requests).

XMLHttpRequest的2级标准(还是一个工作草案)定义FormData的接口。此接口允许将File对象附加到 XHR 请求(Ajax 请求)。

Btw, this is a new feature - in the past, the "hidden-iframe-trick" was used (read about that in my other question).

顺便说一句,这是一个新功能 - 过去,使用了“隐藏的 iframe 技巧”(在我的另一个问题中阅读)。

This is how it works (example):

这是它的工作原理(示例):

var xhr = new XMLHttpRequest(),
    fd = new FormData();

fd.append( 'file', input.files[0] );
xhr.open( 'POST', 'http://example.com/script.php', true );
xhr.onreadystatechange = handler;
xhr.send( fd );

where inputis a <input type="file">field, and handleris the success-handler for the Ajax-request.

其中input是一个<input type="file">字段,handler是 Ajax 请求的成功处理程序。

This works beautifully in all browsers (again, except IE).

这在所有浏览器中都能很好地工作(同样,IE 除外)。

Now, I would like to make this functionality work with jQuery. I tried this:

现在,我想让这个功能与 jQuery 一起使用。我试过这个:

var fd = new FormData();    
fd.append( 'file', input.files[0] );

$.post( 'http://example.com/script.php', fd, handler );

Unfortunately, that won't work (an "Illegal invocation" error is thrown - screenshot is here). I assume jQuery expects a simple key-value object representing form-field-names / values, and the FormDatainstance that I'm passing in is apparently incompatible.

不幸的是,这不起作用(抛出“非法调用”错误 -屏幕截图在这里)。我假设 jQuery 需要一个简单的键值对象来表示表单字段名称/值,而FormData我传入的实例显然不兼容。

Now, since it is possible to pass a FormDatainstance into xhr.send(), I hope that it is also possible to make it work with jQuery.

现在,由于可以将FormData实例传递给xhr.send(),我希望它也可以与 jQuery 一起使用。



Update:

更新:

I've created a "feature ticket" over at jQuery's Bug Tracker. It's here: http://bugs.jquery.com/ticket/9995

我在 jQuery 的 Bug Tracker 上创建了一个“功能票”。它在这里:http: //bugs.jquery.com/ticket/9995

I was suggested to use an "Ajax prefilter"...

有人建议我使用“Ajax 预过滤器”...



Update:

更新:

First, let me give a demo demonstrating what behavior I would like to achieve.

首先,让我给出一个演示来演示我想要实现的行为。

HTML:

HTML:

<form>
    <input type="file" id="file" name="file">
    <input type="submit">
</form>

JavaScript:

JavaScript:

$( 'form' ).submit(function ( e ) {
    var data, xhr;

    data = new FormData();
    data.append( 'file', $( '#file' )[0].files[0] );

    xhr = new XMLHttpRequest();

    xhr.open( 'POST', 'http://hacheck.tel.fer.hr/xml.pl', true );
    xhr.onreadystatechange = function ( response ) {};
    xhr.send( data );

    e.preventDefault();
});

The above code results in this HTTP-request:

上面的代码导致这个 HTTP 请求:

multipartformdata

多部分数据

This is what I need- I want that "multipart/form-data" content-type!

这就是我需要的- 我想要“多部分/表单数据”内容类型!



The proposed solution would be like so:

建议的解决方案如下:

$( 'form' ).submit(function ( e ) {
    var data;

    data = new FormData();
    data.append( 'file', $( '#file' )[0].files[0] );

    $.ajax({
        url: 'http://hacheck.tel.fer.hr/xml.pl',
        data: data,
        processData: false,
        type: 'POST',
        success: function ( data ) {
            alert( data );
        }
    });

    e.preventDefault();
});

However, this results in:

但是,这会导致:

wrongcontenttype

错误的内容类型

As you can see, the content type is wrong...

如您所见,内容类型错误...

回答by pradeek

I believe you could do it like this :

我相信你可以这样做:

var fd = new FormData();    
fd.append( 'file', input.files[0] );

$.ajax({
  url: 'http://example.com/script.php',
  data: fd,
  processData: false,
  contentType: false,
  type: 'POST',
  success: function(data){
    alert(data);
  }
});

Notes:

笔记:

  • Setting processDatato falselets you prevent jQuery from automatically transforming the data into a query string. See the docsfor more info.

  • Setting the contentTypeto falseis imperative, since otherwise jQuery will set it incorrectly.

  • 设置processDatafalse允许您阻止 jQuery 自动将数据转换为查询字符串。有关更多信息,请参阅文档

  • 设置contentTypetofalse是必须的,否则 jQuery会错误地设置它

回答by BenSwayne

There are a few yet to be mentioned techniques available for you. Start with setting the contentType property in your ajax params.

有一些尚未提及的技术可供您使用。首先在 ajax 参数中设置 contentType 属性。

Building on pradeek's example:

以 pradeek 的示例为基础:

$('form').submit(function (e) {
    var data;

    data = new FormData();
    data.append('file', $('#file')[0].files[0]);

    $.ajax({
        url: 'http://hacheck.tel.fer.hr/xml.pl',
        data: data,
        processData: false,
        type: 'POST',

        // This will override the content type header, 
        // regardless of whether content is actually sent.
        // Defaults to 'application/x-www-form-urlencoded'
        contentType: 'multipart/form-data', 

        //Before 1.5.1 you had to do this:
        beforeSend: function (x) {
            if (x && x.overrideMimeType) {
                x.overrideMimeType("multipart/form-data");
            }
        },
        // Now you should be able to do this:
        mimeType: 'multipart/form-data',    //Property added in 1.5.1

        success: function (data) {
            alert(data);
        }
    });

    e.preventDefault();
});

In some cases when forcing jQuery ajax to do non-expected things, the beforeSendevent is a great place to do it. For a while people were using beforeSendto override the mimeType before that was added into jQuery in 1.5.1. You should be able to modify just about anything on the jqXHR object in the before send event.

在某些情况下,当强制 jQuery ajax 做非预期的事情时,beforeSend事件是一个很好的地方。有一段时间,人们beforeSend在 1.5.1 中将 mimeType 添加到 jQuery 之前使用覆盖它。您应该能够在 before send 事件中修改 jqXHR 对象上的任何内容。

回答by Lucky

You can send the FormData object in ajax request using the following code,

您可以使用以下代码在 ajax 请求中发送 FormData 对象,

$("form#formElement").submit(function(){
    var formData = new FormData($(this)[0]);
});

This is very similar to the accepted answer but an actual answer to the question topic. This will submit the form elements automatically in the FormData and you don't need to manually append the data to FormData variable.

这与接受的答案非常相似,但却是对问题主题的实际答案。这将在 FormData 中自动提交表单元素,您无需手动将数据附加到 FormData 变量。

The ajax method looks like this,

ajax 方法看起来像这样,

$("form#formElement").submit(function(){
    var formData = new FormData($(this)[0]);
    //append some non-form data also
    formData.append('other_data',$("#someInputData").val());
    $.ajax({
        type: "POST",
        url: postDataUrl,
        data: formData,
        processData: false,
        contentType: false,
        dataType: "json",
        success: function(data, textStatus, jqXHR) {
           //process data
        },
        error: function(data, textStatus, jqXHR) {
           //process error msg
        },
});

You can also manually pass the form element inside the FormData object as a parameter like this

您还可以手动将 FormData 对象内的表单元素作为参数传递,如下所示

var formElem = $("#formId");
var formdata = new FormData(formElem[0]);

Hope it helps. ;)

希望能帮助到你。;)

回答by talalalshehri

I do it like this and it's work for me, I hope this will help :)

我这样做,它对我有用,我希望这会有所帮助:)

   <div id="data">
        <form>
            <input type="file" name="userfile" id="userfile" size="20" />
            <br /><br />
            <input type="button" id="upload" value="upload" />
        </form>
    </div>
  <script>
        $(document).ready(function(){
                $('#upload').click(function(){

                    console.log('upload button clicked!')
                    var fd = new FormData();    
                    fd.append( 'userfile', $('#userfile')[0].files[0]);

                    $.ajax({
                      url: 'upload/do_upload',
                      data: fd,
                      processData: false,
                      contentType: false,
                      type: 'POST',
                      success: function(data){
                        console.log('upload success!')
                        $('#data').empty();
                        $('#data').append(data);

                      }
                    });
                });
        });
    </script>   

回答by Rahul Yadav

JavaScript:

JavaScript:

function submitForm() {
    var data1 = new FormData($('input[name^="file"]'));
    $.each($('input[name^="file"]')[0].files, function(i, file) {
        data1.append(i, file);
    });

    $.ajax({
        url: "<?php echo base_url() ?>employee/dashboard2/test2",
        type: "POST",
        data: data1,
        enctype: 'multipart/form-data',
        processData: false, // tell jQuery not to process the data
        contentType: false // tell jQuery not to set contentType
    }).done(function(data) {
        console.log("PHP Output:");
        console.log(data);
    });
    return false;
}

PHP:

PHP:

public function upload_file() {
    foreach($_FILES as $key) {
        $name = time().$key['name'];
        $path = 'upload/'.$name;
        @move_uploaded_file($key['tmp_name'], $path);
    }
}

回答by dmnkhhn

You can use the $.ajax beforeSendevent to manipulate the header.

您可以使用 $.ajaxbeforeSend事件来操作标头。

beforeSend: function(xhr) { 
    xhr.setRequestHeader('Content-Type', 'multipart/form-data');
}

See this link for additional information: http://msdn.microsoft.com/en-us/library/ms536752(v=vs.85).aspx

有关其他信息,请参阅此链接:http: //msdn.microsoft.com/en-us/library/ms536752(v=vs.85).aspx

回答by Rohit

If you want to submit files using ajax use "jquery.form.js" This submits all form elements easily.

如果您想使用 ajax 提交文件,请使用“jquery.form.js” 这可以轻松提交所有表单元素。

Samples http://jquery.malsup.com/form/#ajaxSubmit

示例 http://jquery.malsup.com/form/#ajaxSubmit

rough view :

粗略的看法:

<form id='AddPhotoForm' method='post' action='../photo/admin_save_photo.php' enctype='multipart/form-data'>



<script type="text/javascript">
function showResponseAfterAddPhoto(responseText, statusText)
{ 
    information= responseText;
    callAjaxtolist();
    $("#AddPhotoForm").resetForm();
    $("#photo_msg").html('<div class="album_msg">Photo uploaded Successfully...</div>');        
};

$(document).ready(function(){
    $('.add_new_photo_div').live('click',function(){
            var options = {success:showResponseAfterAddPhoto};  
            $("#AddPhotoForm").ajaxSubmit(options);
        });
});
</script>

回答by user4757231

Instead of - fd.append( 'userfile', $('#userfile')[0].files[0]);

代替 - fd.append( 'userfile', $('#userfile')[0].files[0]);

Use - fd.append( 'file', $('#userfile')[0].files[0]);

用 - fd.append( 'file', $('#userfile')[0].files[0]);

回答by DoodleKana