【问题标题】:AJAX File Upload with XMLHttpRequest使用 XMLHttpRequest 上传 AJAX 文件
【发布时间】:2012-05-15 13:28:24
【问题描述】:

我知道有很多类似的问题,但我仍然没有找到解决我的问题的方法。 我正在尝试使用 XMLHttpRequest 上传文件,因此我开发了以下代码:

var sendFiles = function(url,onload,onerror,file,headers){
    var xhr = XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHttp'),
    upload = xhr.upload;
    API.addEvent(xhr,'readystatechange',function(){
        if(xhr.readyState==4)
            if((xhr.status>=200 && xhr.status<300) || xhr.status==304){
                this.response = this.response || this.responseText;
                onload.call(xhr);
            }else onerror.call(xhr);
    });
    xhr.open('POST',url,true);
    for(var n=0;n<headers.length;n++)
        xhr.setRequestHeader(headers[n]);
    xhr.send(file);
    return xhr;
};

而 PHP 端的脚本是:

<?php
header('Content-type: text/html;charset=ISO-8859-1');
$status = 0;
if(@copy($_FILES['file']['tmp_name'],'test\\' . $_FILES['file']['name']))
    $status = 1;
else
    $err = '0';
echo '{
    "status": ' . $status . '
}';
?>;

但是 var $_FILES['file'] 似乎是空的,这意味着文件没有被发送到服务器。 然后我决定在下面的代码中使用 FormData 对象

var sendFiles = function(url,onload,onerror,file,headers){
    var xhr = XMLHttpRequest ? new XMLHttpRequest() : new    ActiveXObject('Microsoft.XMLHttp'),
    upload = xhr.upload,
    formData = new FormData();
    formData.append('file',file);
    API.addEvent(xhr,'readystatechange',function(){
        if(xhr.readyState==4)
            if((xhr.status>=200 && xhr.status<300) || xhr.status==304){
                this.response = this.response || this.responseText;
                onload.call(xhr);
            }else onerror.call(xhr);
    });
    xhr.open('POST',url,true);
    for(var n=0;n<headers.length;n++)
        xhr.setRequestHeader(headers[n]);
    xhr.send(formData);
    return xhr;
};

它确实有效,但文件大小只有 8mb 左右。当我尝试发送大小超过 8mb 的文件时,var $_FILES['file'] 再次变为空

注意:“文件”变量对应于类似 document.getElementsById('fileInput').files[0];

【问题讨论】:

  • 你的ini文件上传文件大小限制是多少?

标签: javascript ajax file upload xmlhttprequest


【解决方案1】:

为了避免post_max_size的限制问题……而且两边也出现内存不足的问题:

在客户端

  • 使用 PUT 代替 POST :

    xhr.open("put", "upload.php", true);

  • 添加自定义标题以指定原始文件名和文件大小:

    xhr.setRequestHeader("X-File-Name", file.name);
    xhr.setRequestHeader("X-File-Size", file.size);

  • 在您的 XHR 发送方法中直接使用 File 对象:

    xhr.send(file);

    请注意,File 对象可以直接通过您的 input[type=file] DOM 对象的“files”属性获取

在服务器端

  • 通过 $_SERVER 读取自定义标题:

    $filename = $_SERVER['HTTP_X_FILE_NAME'];
    $filesize = $_SERVER['HTTP_X_FILE_SIZE'];

  • 使用 php://input 读取文件数据:

    $in = fopen('php://input','r');

然后您就可以无限制地发送非常大的文件(1GB 或更多)!!!

此代码适用于 FireFox 4+、Chrome 6+、IE10+

【讨论】:

  • 很好的解释,谢谢,但您的解决方案有两个限制。第一:如果我直接在 XHR.send 方法中使用 File 对象,我不能发送多个文件。只有一个文件。第二:如 PHP 手册中所写“使用php://input 打开的流只能读取一次”。这再次意味着使用您的技术只能对一个文件发出一个请求。您有更多解决方案如何在 XHR.send 方法中直接使用 'php://input' 和 File 对象发送多个文件吗?我尝试循环 xhr.send(file[n]) 但 readystate 属性出现问题。
  • 是的,每次调用 PHP 脚本都是针对一个文件的,所以如果您想同时发送许多 相关 文件,只需为每个文件分配一个 XHR在客户端,当所有发送完成后,只需调用一个引用所有文件的最终 php 脚本,然后对这些相关文件执行您必须执行的操作。我们有“类似于Dropbox”的内部网络应用程序,可以很好地与该方法配合使用
  • 在服务器端如何使用$filename $filesize and $in 复制文件??!我使用copy() 还是move_uploaded_file?我的服务器有一个限制,不允许我上传大于 2 mb 的文件!请帮忙
  • 使用 while($data = fread($in, 1024)) fwrite($out, $data); 和 $out 对服务器上的目标文件的写入打开句柄
【解决方案2】:

更改ini文件中的post_max_size指令

【讨论】:

    【解决方案3】:

    Ajax 调用不会限制大小。这可能是 php ini 文件中的最大文件大小。

    【讨论】:

      猜你喜欢
      • 2011-09-06
      • 1970-01-01
      • 2013-06-12
      • 1970-01-01
      • 2013-01-17
      相关资源
      最近更新 更多