0

我的应用程序有一个上传组件,它成功地使用了 iFrame 中较旧的表单上传方法。我有一个 Ajax 投票,每 1000 毫秒返回一次上传进度。

我正在做功能检测并允许有能力的浏览器通过 xhr2 上传。理论上,我可以访问客户端的进度;无需轮询,进度条更新更流畅优雅!在批量上传结束时,我需要重定向到显示所有上传文件列表的页面。

您可以通过 xhr2 两种方式上传文件:每个文件都是自己上传的,或者您制作一个包含所有文件的“formData”对象。每个都有优点和缺点,我想我正在尝试两全其美,这可能是不可能的。对我来说,“两全其美”将满足以下要求:

  1. 能够随时显示单个文件的进度和文件名
  2. 发送包裹时能够显示“总进度”栏
  3. 在服务器端捕获文件的“包”,并在整个包完成后发回重定向。

这是单文件传输的示例代码。我可以轻松满足标准#1,并且可以通过一些努力为标准#2 编写代码。#3 有点问题,因为客户端只是将一堆单独的文件作为单独的传输发送。

function uploadFile(file) {
      xhr = new XMLHttpRequest();

      xhr.upload.addEventListener("progress", function(evt) {
        if (evt.lengthComputable) {
          //domNode.bar is a cached jQuery object
          domNode.bar.css('width', (evt.loaded / evt.total) * 100 + "%");
          console.log('my current filename is: ' + file.name;
        }
        else {
          // No data to calculate on
        }
      }, false);

      xhr.addEventListener("load", function() {
        console.log("finished upload");
      }, false);

      xhr.open("post", remoteURL, true);

      // Set appropriate headers
      xhr.setRequestHeader("Content-Type", "application/octet-stream");
      xhr.setRequestHeader("X-File-Name", file.name);
      xhr.setRequestHeader("X-File-Size", file.size);
      xhr.setRequestHeader("X-File-Type", file.type);


      // Send the file
      xhr.send(file);
    }
}

这是作为 formData 发送的示例代码。我现在根本无法满足标准#1……。我可以很容易地满足标准#2 和#3:

function uploadFile(form) {
      xhr = new XMLHttpRequest();

      xhr.upload.addEventListener("progress", function(evt) {
        if (evt.lengthComputable) {
          console.log(evt);
          domNode.bar.css('width', (evt.loaded / evt.total) * 100 + "%");
          // no longer have access to the file object
        }
        else {
          // No data to calculate on
        }
      }, false);

      xhr.addEventListener("load", function() {
        console.log(xhr);
      }, false);

      xhr.open("post", remoteURL, true);

      // Set appropriate headers
      xhr.setRequestHeader("Content-Type", "multipart/form-data");

      // Send the form
      xhr.send(form);
    }
}

// just assume that I've used formData.append to build a valid form object, 
// which I have; and that this is triggered by a click event or something
uploadFile(form);

我并非完全没有选择,但在我继续实施之前,我只是想检查一下我没有遗漏任何东西。以下是我看到的选项:

  1. 继续只使用 Ajax 调用来取得进展。不太流畅,这与我们的设计目标背道而驰,但好处是我不需要使用 iFrame 进行上传,因为我有 xhr2 API。当流关闭时,我也会得到单个重定向。

  2. 迭代文件并在客户端进行一些繁重的工作以取得进展;除了单个文件进度条,我还可以创建一个算法来跟踪总进度。同时,我向服务器发送一个文件计数,并使用这个计数来推迟重定向 URL,直到最后一个文件到达,然后我可以发送它。

有什么想法吗?

4

1 回答 1

1

如果您想在一个请求中发送所有文件,FormData 是两者中唯一的选择。任一选项都允许您涵盖第 1 点和第 2 点。

既然你问到其他 API,我觉得提到我维护的跨浏览器上传工具:Fine Uploader是有道理的。我的库提供回调,让您轻松实现目标#1 和#2。就#3 而言,Fine Uploader 在单独的请求中发送每个文件。但是,使用 Fine Uploader 的 API 来呈现“总进度”栏并不难。我已经在一个使用 Fine Uploader 的项目中做到了这一点。鉴于您指定的要点,该库提供了一堆回调并公开了一个对您应该有用的综合 API。

请注意,上传进度目前在 IE9 和更早版本的 Fine Uploader 中不可用,但您应该能够使用您的方法通过 ajax 调用显示进度。您的方法是一种可能的方法,但还有另一种可能的选项,计划在未来进一步审查:使用 Apache/nginx 的 UploadProgress 模块。请参阅功能请求#506

于 2013-04-30T18:35:07.887 回答