Ajax表单上传进度条
Posted
技术标签:
【中文标题】Ajax表单上传进度条【英文标题】:Ajax form upload progress bar 【发布时间】:2013-04-18 12:01:34 【问题描述】:尝试为表单上传制作进度条(旧的 html4 表单上传,而不是新的 HTML5 API)。进度实际上跟踪文件移动后正在完成的其他工作。它的设计方式是流保持打开状态,直到完成额外的工作,然后服务器端方法最终返回,从而关闭流。
我遇到了一些特定于 Chrome 的问题。我也有一个可行的实现,但我希望能得到“更好”的东西。
对于任何可能要求提供代码的人:这里故意不提供。场景解释了问题;代码本身没有“错误”,只会更加混乱。
简而言之,第 1 次尝试失败
-
启动表单上传
在获取某些 JSON 中的进度的 Ajax 调用上设置间隔
将数据呈现到进度条
失败原因:上传流阻塞了页面上的其他活动,并且您在传输过程中无法进行额外的 Ajax 调用。
简而言之,第 2 次尝试失败
-
创建一个包含相同 Ajax 调用的 iFrame
将数据呈现给 iFrame 中的元素(所需的一切都是自包含的,至少不引用“顶部”文档)
结果:
在启动表单上传之前,我可以从 JSON 中呈现“状态:等待”。渲染函数还增加了一个计数器,所以我会看到“尝试#X”。状态等待时,尝试次数会增加。
启动传输后,Ajax 调用成功获得 200,我可以检查响应以查看 JSON 确实存在。
但是,我无法更新 iFrame 中的“shadow DOM”(这是正确的术语吗?)。尝试访问 iFrame 中的节点并对其进行修改失败。甚至计数器也没有增加。
传输完成后,它将成功呈现“状态:完成”,并且计数器会向前跳(计数器正在递增,但将其呈现到 iFrame 只是不起作用)
GRR!
成功尝试
iFrame 不再请求 Ajax。 iframe 的 src 属性设置为返回预渲染进度条的 URL。正在加载到 iframe 中的文档设置为重新加载自身。所以在规定的时间间隔内,它会重新渲染一个“移动”的新进度条。
结果是一个“工作”进度条,尽管有时请求中的延迟会导致 iframe 瞬间空白,这不是我的偏好。
谁能想到更好的方法来做到这一点?是否有可能我可以让 iFrame 中的表单本身而 Ajax 在“顶部”文档中工作?
我主要是想把表现层和数据层分开,但是只要我必须返回一个渲染的进度条,那是行不通的。作为奖励,如果我能找到一种通过 Ajax 更新进度条的方法,我就不会有那些“空白”光点。
【问题讨论】:
您是否尝试过将文件上传提交到 iFrame,该 iFrame 不会阻止页面上的任何内容,但允许发生服务器请求? Alos - 根据您的限制 - 如果您可以访问 HTML5 浏览器,那么现在 XHR 对象上有一个进度事件。但它只支持 Chrome 和 Firefox(可能是 Opera)。绝对不是 IE。 谢谢,isuriel。我认为这将是一些尝试。我还没有这样做。 HTML5 进度事件将使我能够访问“移动”部分,但我仍然需要从服务器访问“移动后”进度。但扭转 iFrame 的角色可能是一种方法。 这个似乎有你需要的一切,以防你使用 jQuery ***.com/questions/15410265/… Oleg,如果我正确阅读了代码,它不会处理“文件移动后”部分。在完成“额外”工作时,它只会保持 100%;这将适用于传输的第一段(移动文件),但它不提供捕获第二段(正在完成的额外工作)进度的机制。 【参考方案1】:要扩展我的评论并提供指导,要执行“隐藏 iframe 文件上传”,您需要一个带有名称的隐藏框架(不是很明显吗?)。
<html>
<body>
<iframe name="file-upload" src="" style="border: none; visibility: hidden; width: 0; height: 0; position: absolute; top: 0; left: 0;"></iframe>
The iframe shouldn't be visible, just pretend I didn't use inline styles though.
<form id="uploadForm" action="anaction.php" enctype="whatever-you-need-here" method="post">
File: <input type="file" /><br />
<input type="submit" value="Upload" />
</form>
</body>
</html>
到目前为止所有非常标准的东西。接下来是 javascript:
var form = document.getElementById("uploadForm");
form.onsubmit = function()
console.log("The form has been submitted, start progress!");
form.target = "file-upload"; // the name of the iframe
// Go about your business, when "Upload" is pressed the file will be submitted
// to the iframe so you'd start your progress requests on form submit.
忽略不良做法,这是一个简单的例子。
【讨论】:
似乎不起作用。我的编码类型是“multipart/form-data”;上传有效,但在 Chrome 中仍然存在阻塞条件。不过,我不确定如何判断它是否实际上是从 iFrame 发送文件;看起来它仍在从顶部文档发送它。 注意:它似乎在 Firefox 中工作,有点:代码很好,但表单上传不断使浏览器崩溃。 ;) 我猜最近表单上传的错误实现。 我取消了表单上的操作(如果您也将其关闭也很可疑),并且 IFrame 可能需要一个空的src
属性才能开始 - 我不确定。除此之外,我以前使用过这种方法没有任何问题。
是的,我有一个空的 src 属性并包含一个动作。上传确实启动了;它只是不允许 Ajax 调用进度(在 Chrome 中)。
@Azd325 如果使用足够新的 jQuery 版本(我认为是 1.9)然后:$(formSelector).prop("target", "file-upload");
否则:$(formSelector)[0].target = "file-upload";
【参考方案2】:
老实说,我为一个应用做所有的前端开发,我也在寻找同样的东西。首先,我尝试使用我们的 socket.io 发送回一个数字,然后将其转换为百分比。然后,我会将其应用于 twitter 引导程序栏。
我最终做和坚持的是使用好的上传器http://fineuploader.com/ 文档有点烂,你必须稍微玩弄它,但它有一个内置事件,在上传一些东西时会一遍又一遍地触发实际上会返回你的进度。
【讨论】:
如果您有任何改进文档的建议,请在 Fine Uploader Github 项目中打开a support ticket。我已经竭尽全力使文档完整,但我想知道它是否可以进一步改进。 我会查看 Fine Uploader;我只是想知道它将如何处理我拥有的非常规用例(在完成一些“额外”工作之前,服务器不会返回并关闭流)。 @GregPettit 这取决于您的期望。如此处所述,您的用例对我来说并没有不合常规(除非我遗漏了什么)。【参考方案3】:我决定使用:http://blueimp.github.io/jQuery-File-Upload/,因为它是免费的,并且提供了不错的进度条。
【讨论】:
看起来很有希望,Garath。我会调查的!【参考方案4】:上次我只是将带有数据的表单提交到一些不可见的 iframe,然后我就可以忘记它了。
接下来我开始轮询一些 URL/REST API 的进度。
一旦提交完成 - 事件将触发,其处理程序将停止进度轮询。
我认为这种方法没有任何问题,但由于某种原因,您的两种方法似乎都与我所描述的不符,所以我将其作为答案。
如果您使用 jQuery,最好的方法是使用 jQuery Form plugin“ajaxify”您的表单。示例可以参考这个问题:File upload progress bar with jQuery。
【讨论】:
这似乎是 izuriel 在 cmets 中所建议的。我还没有尝试过,但这个想法是合理的。我会回来报告的!以上是关于Ajax表单上传进度条的主要内容,如果未能解决你的问题,请参考以下文章