首页 文章

如何在jQuery中使用Ajax请求发送FormData对象? [重复]

提问于
浏览
416

这个问题在这里已有答案:

XMLHttpRequest Level 2标准(仍然是工作草案)定义了 FormData 接口 . 此接口允许将 File 对象附加到XHR请求(Ajax请求) .

顺便说一句,这是一个新功能 - 在过去,使用了"hidden-iframe-trick"(在my other question中阅读) .

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

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

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

这在所有浏览器中都很漂亮(除了IE之外) .

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

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

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

不幸的是,这不起作用(抛出"Illegal invocation"错误 - screenshot is here) . 我假设jQuery需要一个表示form-field-names / values的简单键值对象,而我传入的 FormData 实例显然是不兼容的 .

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


Update:

我've created a 175167 over at jQuery' s Bug Tracker . 它在这里:http://bugs.jquery.com/ticket/9995

我被建议使用“Ajax prefilter”......


Update:

首先,让我演示一个演示我想要实现的行为的演示 .

HTML:

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

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

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

multipartformdata

This is what I need - 我想要"multipart/form-data"内容类型!


建议的解决方案是这样的:

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

但是,这导致:

wrongcontenttype

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

9 回答

  • 26

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

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

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

  • -1

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

    样品http://jquery.malsup.com/form/#ajaxSubmit

    粗略观点:

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

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

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

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

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

    您也可以手动将FormData对象中的表单元素作为参数传递给它

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

    希望能帮助到你 . ;)

  • 5

    而不是 - fd.append( 'userfile', $('#userfile')[0].files[0]);

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

  • 2
  • 5

    您可以使用$ .ajax beforeSend 事件来操纵标头 .

    ...

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

    ...

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

  • 3

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

    <div id="data">
            <form>
                <input type="file" name="userfile" id="userfile" size="20" />
                

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

    我相信你可以这样做:

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

    processData 设置为false可以防止jQuery自动将数据转换为查询字符串 . 有关详细信息,请参阅the docs .

    contentType 设置为false是必要的,否则jQuery will set it incorrectly .

  • 2

    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:

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

相关问题