XMLHttpRequest Level 2标准(仍然是工作草案)定义了FormData接口。该接口允许将File对象追加到XHR-requests (Ajax-requests)。

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

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

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

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

现在,既然可以将一个FormData实例传递给xhr.send(),我希望也可以让它与jQuery一起工作。


更新:

我在jQuery的Bug跟踪器上创建了一个“功能票”。网址:http://bugs.jquery.com/ticket/9995

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


更新:

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

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请求:

这就是我需要的-我想要“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();
});

然而,这会导致:

如您所见,内容类型是错误的……


当前回答

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

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

其他回答

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

以普拉迪克为例:

$('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事件是一个很好的地方。在mimeType被添加到jQuery 1.5.1之前,有一段时间人们使用beforeSend来覆盖mimeType。您应该能够在发送前事件中修改jqXHR对象上的任何内容。

你可以在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
        },
});

您还可以手动将form元素作为参数传递到FormData对象中,如下所示

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

希望能有所帮助。;)

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

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

我相信你可以这样做:

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自动将数据转换为查询字符串。更多信息请参阅文档。 将contentType设置为false是必要的,否则jQuery将不正确地设置它。

如果你想使用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>