问题

使用jQuery的ajax函数将文件发送到服务器端的PHP脚本时出现问题. 可以使用 $('#fileinput').attr('files')获取文件列表,但是如何将此数据发送到服务器?使用文件输入时,serverside php-script上的结果数组( $ _ POST )为0( NULL ).

我知道这是可能的(虽然我没有找到任何jQuery解决方案,直到现在,只有Prototye代码( http://webreflection.blogspot.com/2009/03/safari-4-multiple-upload-with-progress.html )).

这似乎是比较新的,所以请不要提及文件上传是不可能通过XHR / Ajax,因为它一定是工作.

我需要Safari 5中的功能,FF和Chrome会很好,但不是必需的.

我的代码现在是:

$.ajax({
    url: 'php/upload.php',
    data: $('#file').attr('files'),
    cache: false,
    contentType: 'multipart/form-data',
    processData: false,
    type: 'POST',
    success: function(data){
        alert(data);
    }
});


解决方法

从Safari 5 / Firefox 4开始,最容易使用 FormData 类:

var data = new FormData();
jQuery.each(jQuery('#file')[0].files, function(i, file) {
    data.append('file-'+i, file);
});

现在你有一个 FormData 对象,可以和XMLHttpRequest一起发送.

jQuery.ajax({
    url: 'php/upload.php',
    data: data,
    cache: false,
    contentType: false,
    processData: false,
    type: 'POST',
    success: function(data){
        alert(data);
    }
});

必须将 contentType 选项设置为 false ,强制jQuery不为您添加 Content-Type 边界字符串将从中丢失. 此外,您必须将 processData 标志设置为false,否则jQuery将尝试将您的 FormData 转换为字符串,这将失败.

您现在可以使用以下方式在PHP中检索文件:

$_FILES['file-0']

(只有一个文件 file-0 ,除非您在文件输入中指定了 multiple 属性,在这种情况下, .)

对旧版浏览器使用 FormData模拟

var opts = {
    url: 'php/upload.php',
    data: data,
    cache: false,
    contentType: false,
    processData: false,
    type: 'POST',
    success: function(data){
        alert(data);
    }
};
if(data.fake) {
    // Make sure no text encoding stuff is done by xhr
    opts.xhr = function() { var xhr = jQuery.ajaxSettings.xhr(); xhr.send = xhr.sendAsBinary; return xhr; }
    opts.contentType = "multipart/form-data; boundary="+data.boundary;
    opts.data = data.toString();
}
jQuery.ajax(opts);

从现有表单创建FormData

还可以使用现有表单对象的内容创建FormData对象,而不是手动迭代文件:

var data = new FormData(jQuery('form')[0]);

使用PHP原生数组,而不是计数器

只需将文件元素命名为相同,并将名称括在括号中:

jQuery.each(jQuery('#file')[0].files, function(i, file) {
    data.append('file[]', file);
});

$ _ FILES ['file'] 将是一个数组,包含每个上传文件的文件上传字段.我实际上推荐这个超过我的初始解决方案,因为它更容易迭代.




相关问题推荐