之前写过一个仿163网盘无刷新多文件上传系统,已经对无刷新上传文件的原理做了详细的分析。 兼容:ie6/7/8, firefox 3.5.5, opera 10.01, safari 4.0.3, chrome 3.0
ps:由于需要后台,要测试系统请下载实例测试。
【upload】 程序中最重要的方法就是upload了,调用它就可以进行无刷新上传。 如果设置了timeout属性的话,会自动设置计时器: if ( this.timeout > 0 ) {
this._timer = setTimeout( $$F.bind(this._timeout, this), this.timeout * 1000 ); } ps:经测试,小于0的延时时间,ie会取消执行,而其他浏览器会当成0执行。 程序有一个_sending属性用来判断上传状态。 最后提交表单就开始上传了。
程序使用_setIframe函数来创建无刷新需要的iframe。 由于ie中iframe的name不能修改的问题,要这样创建iframe: Code
var iframename = "QUICKUPLOAD_" + QuickUpload._counter++, iframe = document.createElement( $$B.ie ? "<iframe name=\"" + iframename + "\">" : "iframe"); iframe.name = iframename; iframe.style.display = "none"; ps:关于iframe的name的问题参考这里的iframe部分。 为了能在文件上传完成后执行回调函数,会在iframe的onload中执行_finish函数: Code
var finish = this._fFINISH = $$F.bind(this._finish, this); if ( $$B.ie ) { iframe.attachEvent( "onload", finish ); } else { iframe.onload = $$B.opera ? function(){ this.onload = finish; } : finish; }
iframe的加载还有一个问题,测试以下代码: Code
<body><div id="msg">状态:</div></body> <script> var msg = document.getElementById("msg"); var iframe = document.createElement("iframe"); iframe.onload = function(){ msg.innerHTML += "onload,"; } document.body.appendChild(iframe); iframe.src = "http://cloudgamer.cnblogs.com/" </script>
估计在safari和chrome在appendChild之后就进行第一次加载,并且在设置src之前加载完毕,所以触发了两次。 那么opera, ff和ie可能是第一次加载太慢,第二次覆盖了第一次的,所以只触发了一次onload。 针对加载过快的问题,可以在onload的时候根据_sending确定之前是否上传状态来解决。 opera还有一个麻烦的问题,测试下面代码: Code
<body> <div id="msg">状态:</div> <form action="http://cloudgamer.cnblogs.com/" target="ifr"> </form> </body> <script> var msg = document.getElementById("msg"); var iframe = document.createElement("iframe"); iframe.name = "ifr"; iframe.onload = function(){ msg.innerHTML += "onload,"; } document.body.appendChild(iframe); msg.innerHTML += "submit,"; document.forms[0].submit(); </script>
虽然不知道原因,办法还是有的,一个是appendChild前设一个src,还可以在第一次onload中重新设置onload,像程序那样。 ff的onload还有一个问题,在出现ERROR_INTERNET_CONNECTION_RESET(文件大小超过服务器限制)之类的服务器错误时,即使加载完成也不会触发onload,暂时找不到解决办法。 iframe有一个缺陷是只能用onload判断加载完成,但没有办法判断是否加载成功。
程序使用_setForm函数来创建用来提交数据的form。 要实现无刷新上传,要对form进行特殊的处理: $$.extend(form, {
target: this._iframe.name, method: "post", encoding: "multipart/form-data" }); ps:详细看这里的无刷新上传部分。 由于form是手动插入的,为了不影响原来页面布局还要设置一下form样式,使它“隐形”起来: $$D.setStyle(form, {
padding: 0, margin: 0, border: 0, backgroundColor: "transparent", display: "inline" });
file.form && $$E.addEvent(file.form, "submit", $$F.bind(this.remove, this));
remove方法是用来移除程序的,包括移除form。 最后把form插入到dom: file.parentNode.insertBefore(form, file).appendChild(file);
先把form插入到file控件之前,然后把file插入到form,这样就能保证file在原来的位置上了。 (责任编辑:admin) |