xhr2文件上传 - 使用formData访问文件名

时间:2013-04-30 16:52:56

标签: javascript xmlhttprequest

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

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

您可以通过xhr2以两种方式上传文件:每个文件都是自己的上传文件,或者您创建一个包含所有文件的“formData”对象。每个都有好处和缺点,我想我正在努力获得两个世界中最好的,这可能是不可能的。对我来说,“两全其美”都符合这些要求:

  1. 能够显示各个文件的进度和文件名
  2. 能够在发送包裹时显示“总进度”栏
  3. 捕获服务器端文件的“包”,并在完成整个包后发回重定向。
  4. 以下是单文件传输的示例代码。我可以轻松地满足标准#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,直到最后一个文件到达,然后我可以发送它。

    3. 有什么想法吗?

1 个答案:

答案 0 :(得分:1)

如果要在一个请求中发送所有文件,FormData是两者中唯一的选项。任何一个选项都可以覆盖1点和1点。 2.

由于您询问了其他API,我觉得提及我维护的跨浏览器上传工具是合理的:Fine Uploader。我的图书馆提供回调功能,让您轻松实现目标#1& #2。就#3而言,Fine Uploader在单独的请求中发送每个文件。但是,使用Fine Uploader的API来呈现“总进度”栏并不难。我在使用Fine Uploader的项目中做到了这一点。该库提供了一系列回调,并根据您指定的要点公开了一个对您有用的综合API。

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