xhr2文件上传 - 使用formData访问文件名
我有一个上传组件到我的应用程序,它成功地在iFrame中使用旧的表单上传方法。我有一个Ajax轮询,每1000ms返回一次上传进度。xhr2文件上传 - 使用formData访问文件名
我正在做功能检测,并允许有能力的浏览器通过xhr2上传。理论是,我可以在客户端获得进展;无需轮询,进度条更新更加流畅和优雅!在批量上传结束时,我需要重定向到显示上传的所有文件列表的页面。
你可以通过xhr2上传两个文件:每个文件都是自己上传的,或者你制作一个包含所有文件的“formData”对象。每个人都有好处和缺点,我想我正在努力获得两全其美的好处,这可能是不可能的。在“两全其美”我会满足这些要求:
- 能够显示进度和单个文件的文件名,因为他们去
- 能够作为包是显示一个“总进度”栏发送
- 捕获服务器端文件的“包”,并在整个包完成时发回重定向。
下面是单个文件传输的示例代码。我可以轻松满足标准#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);
我不是完全没有选择,但在此之前我实现前进我只是想,我不是缺少什么完整性检查。以下是我看到的选项:
继续仅使用Ajax调用进度。不太流畅,这与我们的设计目标相反,但好处是我不需要使用iFrame进行上传,因为我拥有xhr2 API。当流关闭时,我也会得到单个重定向。
对文件进行迭代,并在客户端进行一些繁重的工作;除了单个文件进度条之外,我还可以创建一个算法来跟踪总体进度。同时,我向服务器发送文件计数,并使用此计数延迟重定向URL,直到最后一个文件到达,然后我可以发送它。
有什么想法?
如果你想发送一个请求中的所有文件,FormData是你唯一的选择。任一选项都允许您覆盖点1 & 2.
由于您询问了其他API,我觉得提到我维护的跨浏览器上传工具是合理的:Fine Uploader。我的图书馆提供回调,可以让您轻松实现目标#1 &#2。就#3而言,Fine Uploader会在单独的请求中发送每个文件。但是,使用Fine Uploader的API来呈现“全面进度”栏并不困难。我在一个使用Fine Uploader的项目中完成了这项工作。该库提供了一系列回调函数,并提供了一个综合的API,在给定了您指定的点的情况下,这些API应该对您有用。
请注意,Fine Uploader中的IE9和更高版本目前不提供上传进度,但您应该可以使用您的方法通过ajax调用显示进度。你的方法是一种可能的方法,但是还有另一种可能的选择,计划在将来进一步审查:使用Apache/nginx的UploadProgress模块。请参阅功能请求#506。
谢谢,雷。我一定会考虑Fine Uploader。您是否可以使用Fine Uploader发送附加信息?我总是可以预先计算出预期的文件数量,然后将文件发送给服务器,然后让服务器观看一个计数器,并在预期的编号后发回一些带有重定向URL和“重定向真实”标志的回复的文件已达到...?我发布的URL将设置一个ID,服务器上有一个具有该ID的对象,因此我可以跟踪与该特定“会话”相关的所有上传。 – 2013-04-30 18:44:56
您当然可以通过'params'选项在初始化过程中或上传初始化后的任何时间(即使在您的一个回调函数中)通过'setParams' API方法发送附加信息。还有一个'complete'回调,它将包含一个参数,其中包含您的服务器在响应中包含的任何数据。您可以根据需要使用这些数据。 API,选项,回调等都完全记录在案。您最好的选择是从自述文件的第一页开始,并根据您的预期用途进行思考。 – 2013-04-30 18:50:22
太棒了,谢谢你的光阴。我会研究Fine Uploader以及其他更一般的建议。如果FU看起来像是我们的答案,那么我们将不得不进行关于许可的离线讨论。 – 2013-04-30 19:01:32
我不相信你应该在发送FormData时设置内容类型,因为浏览器必须设置边界名称。 – idbehold 2013-04-30 18:16:15
谢谢,idbehold。示例代码我从集合类型中获取它;但是,它可能会被忽略。无论哪种方式,转让的作品。我为单个文件示例设置了错误(应该是application/octet-stream,我相信) – 2013-04-30 18:19:33
您正在为单个文件示例设置错误。另外,在单文件示例中,X-File-Size标头是不相关的。请求中的Content-Length标题已包含此信息。 – 2013-04-30 18:25:58