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

然而,这会导致:

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


当前回答

我相信你可以这样做:

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将不正确地设置它。

其他回答

我相信你可以这样做:

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将不正确地设置它。

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

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

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

希望能有所帮助。;)

你可以使用$。ajax beforeSend事件来操作头部。

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

更多信息请参见此链接:http://msdn.microsoft.com/en-us/library/ms536752(v=vs.85).aspx

我这样做,这是我的工作,我希望这将有所帮助:)

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