aspnet简便无刷新文件上传系统_第1页
aspnet简便无刷新文件上传系统_第2页
aspnet简便无刷新文件上传系统_第3页
aspnet简便无刷新文件上传系统_第4页
aspnet简便无刷新文件上传系统_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、简便无刷新文件上传系统z前写过一个仿163网盘无刷新多文件上传系统,已经对无刷新上传文件的原理做了详细的 分析而这次的系统主要是针对单个file控件的,便携版,使用更简单,还有更深入的分析 ps: flash实现的效果是好得多,但这不是我研究的范围,也没什么可比性。兼容:ie6/8, firefox 3.5.5, opera 10.01, safari 4.0.3, chrome 3.0ps:由于需要后台,要测试系统请下载实例测试。ps2:在完整实例文件屮,还有一个文件属性查看实例。程序说明upload程序中最重要的方法就是upload 了,调用它就可以进行无刷新上传。upload的过程是这样

2、的,首先用stop方法停止上一次上传,并判断是否选择文件。然后分别调用_setlframe, _setform 和_setlnput,生成需要的 iframe, form 和 input。如果设置了 timeout属性的话,会自动设置计时器:复制代码代码如下:if (this.timeout > 0 ) this._timer = settimeout( $f.bind(this._timeout, this), this.timeout * 1000 ); ps:经测试,小于0的延时时间,ie会取消执行,而其他浏览器会当成0执行。程序有一个.sending属性用來判断上传状态。在sto

3、p (停止),dispose (销毁),_finis (完成),_timeout (超时)时会把它设为false。 而在上传开始前要把它设置为true。最后提交表单就开始上传了。iframe程序使用_setlframe函数来创建无刷新需要的iframe。由于ie中iframe的name不能修改的问题,要这样创建iframe:复制代码代码如下:var 讦ramename = "quickuploadj + quickupload._counter+,iframe = document.createeleme nt( $b.ie ? h<iframe n ame=,h + if r

4、am en ame +: niframen); = iframe name;iframe.style.display = "no ne”;ps:关t iframe的name的问题参考这里的iframe部分。ie8已经可以修改name?,但在非标准(怪辟)模式下还是不能修改。其中使用了一个quickupload函数自身的.counter属性做计算器,这就能保证各个实例的 iframe的name就不会重复。为了能在文件上传完成后执行回调函数,会在iframe的onload中执行_finish函数:复制代码代码如下:var finish = this._ffinish

5、 = $f.bind(this._finish,this);if($b.ie)iframe.attacheventf nonloact, finish ); else iframe.onload = $b.opera ? functi on() this, on load = fin ish;: finish;在ie需要用attachevent来绑定onload,因为在ie中直接设置onload是无效的。 除了用 attachevent 还可以用 onreadystatechange 代替。至于原因我也不清筑,详细参考“判断讦rame是否加载完成的完美方法”。iframe的加载还有一个问题,测

6、试以下代码:复制代码代码如下:<bodyxdiv id=”msg状态:</divx/body><script>var msg = document.getelementbyldmsg“);var iframe = document.createelementiframe“);iframe.onload = function() msg.innerhtml += ''onload/'docume ntbody.appendchild(iframe);讦 rame.src = n</script>结果safari, chrome都会

7、触发onload两次,而opera, ff和ie (请自行兼容)都是1次。估计在safari和chrome在appendchild z后就进行第一次加载,并且在设置src z前加载完 毕,所以触发了两次。如果在插入body之前给iframe随便设置一个src (除了空值),间接加长第一次加载,那么 也只触发一次了。ps:不设置或空值的src相当于链接到“about:blank”(空白页)。那么opera, ff和ie可能是第一次加载太慢,第二次覆盖了第一次的,所以只触发了一次on loadops:也可能是其他原因,例如浏览器优化之类的,我也不确定。针对加载过快的问题,可以在onload的时候根

8、据_sending确定z前是否上传状态来解决。虽然没测试出来,会不会有.sending设置z后submit z前刚好触发第一次onload的情况呢? 针对这个问题,在upload方法中会把.sending放在submit之后设置。那如果在submit之后_sending设置之前就触发了 onload呢?(冏)这个情况基本不会出现,如果真的出现,就把.sending设置放到submit前面吧。opera还有一个麻烦的问题,测试下面代码:复制代码代码如下:<body><div id="msg">状态:</div><form action

9、=h target=,ifr"></form></body><script>var msg = document.getelementbyldcsg11);var iframe = document.createelement(,iframe'1); = nifrh;iframe.onload = function() msg.innerhtml += "onload,11;docume nt.body.appe ndchild(iframe);msg.innerhtml += "submit

10、,"docume ntforms0.submit();</script>ie 和 ff 显示 submit,onload, safari 和 chrome 显示的是 onloadubmionload,跟上面的分析 一致。而opera去卩显示submit,onload,onload,两次onload都是在submit之后触发的。这个情况就不能单纯用.sending来解决了。是不是submit不能使iframe収消加载呢?在appendchild之前设一个src,结果正常的只触发onload 一次,看来是可以的啊。虽然不知道原因,办法还是有的,一个是appendchild前设

11、一个src,还可以在第一次onload 中重新设置onload,像程序那样。但这两个方法都存在不确定性,不能完全解决问题,但也找不到更好的方法了。ff的onload还有一个问题,在出现error_internet_connection_reset (文件大小超过服 务器限制)z类的服务器错误时,即使加载完成也不会触发onload,暂时找不到解决办法。iframe有一个缺陷是只能用onload判断加载完成,但没有办法判断是否加载成功。没有类似xmlhttp的status的东西,遇上404 z类的错误也没办法判别出来。在使用时要做好这方面的处理,例如说明允许上传文件大小,超时时间,如何处理长时间无

12、 响应等。form程序使用jetform函数来创建用来提交数据的form。要实现无刷新上传,要对form进行特殊的处理:复制代码代码如下:$.extend(form, target: , method: "post", encoding: "multipart/form-data");ps:详细看这里的无刷新上传部分。由于form是手动插入的,为了不影响原來页面布局还要设置一下form样式,使它“隐形” 起来:复制代码代码如下:$d.setstyle(form, padding: 0, margin: 0, border:

13、0, backgroundcolor: "transparent", display: "inline” );还要注意的是,同一个表单控件只能对应一个form。 如果file控件本身己经有一个form的话,必须在提交前移除:file.form && $e.addevent(file.form, "submit", $f.bind(this.dispose, this);dispose方法是用来销毁程序的,包括移除formo ps:如果提交前submit被覆盖的话要手动执行一-次dispose方法。最后把form插入到dom:fi

14、le.parentnode.insertbefore(form, file).appendchild(file);先把form插入到file控件之前,然后把file插入到form,这样就能保证file在原来的位置上 to【input如果有其他参数要传递,程序会使用_setlnput函数來创建传递数据的表单控件。ftl于生成的form里面只有file控件,要传递其他参数只能用程序生成了。程序用一个jnputs集合来保存当前在form中生成的表单控件。首先根据自定义的parameter属性创建表单控件:复制代码代码如下:for ( name in this.parameter) var in pu

15、t = form n ame;if ( !input) in put = document.createeleme nt(”i nput"); = name; input.type = "hidden”; form.appe ndchild(input);in put.value = this.parameter name;n ewlnputsname = in put;delete oldlnputsname;当form中没有对应name的控件吋,会自动生成一个hidden控件插入到form中。 其中newlnputs是用來记录当前生.成的控件的,而

16、oldlnputs就是jnputs集合。当设置过对应name的控件后,就从oldlnputs小删除对应控件的关联。然后移除oldlnputs关联的控件:for ( name in oldlnputs ) form.removechild( oldlnputsname);这样就能移除上一次生成的无用的控件了。最后重新记录当前控件到nputs方便下次使用。stop如果想停止当前上传操作,可以调用stop方法。一般来说当iframe发生重载时,会取消上一次的载入,那么只要重新设置src就能取消上传 to测试以下代码:复制代码代码如下:<body><iframe id="i

17、fr" name="ifr"x/iframe><form action=" target="ifr"></form></body><script>docum en t.forms0.submit();document.getelementbyld("ifr").src =</script>结果都能取消加载,除了 opera,未知什么原因。有两个方法解决,一个是通过form随便用一个action提交一次,还有就是直接移除iframeo 后一个方法比较方

18、便,程序屮用_removelframe方法直接移除iframeo ps:有更好方法的话记得告诉我。dispose当使用结束或其他原因要销毁程序时,可以调用dispose方法。dispose里面主要做的是移除iframe和form。移除iframe用的是_removelframe方法,首先把onload移除,再把iframe从body移除:var iframe = this._iframe;$b.ie ? iframe.detachevent( "onload", this._ffinish ): (ifirame.onload = null);documentbodyrem

19、ovechild(iframe); this._iframe = null;十分简单,但在ff有一个问题,测试以下代码:复制代码代码如下:<form target="ifr" action="x"><input id="btn" type="submit" value="click"></form><iframe name=,ifrn id="ifr"x/iframe><script>document.getelem

20、 en tbyld(nbt nn).o nclick = fun ction()document.getelementbyldc 讦 rj.o nload = fun ction()this.pare ntnode.removechild(this);</script>提交后都能移除iframe,但ff还一直显示“载入中”的状态。不过解决方法也很简单,用settimeout设置一个延时,让iframe执行完整就可以了。 所以在dispose中是这样调用_removelframe的:复制代码代码如下:if ( $b.firefox ) settimeout($f.bind(this.

21、_removelframe? this), 0); else this._removelframe();至于form的移除就比较简单,在_removeform这样处理:复制代码代码如下:var form = this._form, pare nt = form.parentnode;讦(parent) parent.insertbeforefthis.file, form); parent.removechild(form);this._form = this.jnputs = null;要判断一下parentnode,否则如果parentnode不存在的话后面的会执行岀错。file 的 re

22、set在实例里,有一个用来重置file控件的resetfile两数。重置file控件一般的办法是使所在的form执行reset,但问题是会把其他表单控件也重置了。 以前由于安全问题,file的value是不允许修改的。但现在ff,chrome和safari可以把它设为空值来实现重置:file.value =当然其他值还是不允许的。ps:记忆中以前是不行的,不知有没有记错。对于opera,有一个变通的方法,利用它的type屈性:file.type = "text" file.type = "file"通过修改type得到的file控件,value会自动还原

23、成空值,这样就间接把file控件清空了。 ps:利用这个方法可以间接得到文件路径,但由于变回去后值就清空了,所以没什么用。而ie的表单控件的type设置后是不允许修改的,不能用opera的办法。不过还是有以下方法解决:1,新建一个form,把file插进入后reset,再移除:复制代码代码如下:with(file.parentnode.insertbefore(document.createelement('form'), file) appendchild(file); reset(); removenode(false);好处是使用原生的reset,稳定可靠,但效率低。ps

24、: removenode只有ie和opera支持,如需兼容可改用removechild的方式。2, 利用outerhtml,重建一个file控件:file.outerhtml = file.outerhtml;好处是高效,但由于是新创建的file控件,之前关联的东西都丢失了。ps: ff支持不支持outerhtmlo3, 利用clonenode,复制一个file控件:file.parentnode.replacechild(file.clonenode(false), file);跟上一个方法差不多,但效率更低。4, 利用select方法选中file控件的文本域,再进行清空:file.sele

25、ct(); document.selection.clear();或file.select(); document.selection.clear();看来没什么问题,但file必须能被select (不能是隐藏状态)。ps:这两个方法都只能在ie使用。由于程序屮file是需要关联的,所以方法2和3都不能用。方法4貌似也不错,但有一个致命问题,在ie测试以下代码:复制代码代码如下:<formxinput id="test" name="file" type="file"x/form><script>docume

26、 nt.getelementbyld("testh). on change = fun ction()this.select(); document.selection.clear();this.form.submito;</script>执行到submit会显示“拒绝访问”的错误,原因不清楚,不知是ie故意的还是bug。看来也只能使用方法1 了:复制代码代码如下:function resetfile(file)file.value = ""/ff chrome safariif ( file.value ) if ( $b.ie ) /iewith(

27、file.parentnode.insertbefore(document.createelement('forrrt), file) appendchild(file); reset(); removenode(false); else /operafile.type = "text" file.type = "file" ps:有更好方法的话记得告诉我啊。这个函数并不够通用,最好还是根据实际情况选择需要的方法。使用技巧【上传文件数】在文件上传实例中,各个文件是同时上传的。经测试,浏览器能同吋上传的文件数如下:ie2ff8opera 8chro

28、me 6safari 6由于ie最多同时只能传2个,所以设置更多文件也只能排队,而不能达到同时上传的效果 的。ps:只是目测结果,有错请提出。【传递参数】上传文件实例中,可以传递对应的修改文件名,在使用“一般上传”多个文件一起上传时也 能找到对应的文件名。因为表单控件值传递到后台后,获取数据的顺序跟前台表单控件的排列顺序是一致的。 只要保证前台file控件跟对应表单控件的排列顺序一致就能利用这个特性获取对应的值了。 详细参考后台代码。【回调函数】有两个方法可以响应上传完成回调函数。一种是后台上传完成后,在讦rame输出并执行回调函数或通过parent调用父窗口的冋调函 数。这种比较方便,但必须

29、在iframe里面执行处理,例如文件属性查看实例。另一种是在iframe的onload中执行回调函数。好处是可以把所有处理放在父窗口,iframe可以不做任何处理或用来反馈信息。缺点是有兼容性问题,而且会有加载后没有触发onload的情况(上面的iframe部分有说明)。 上传文件实例中就是在onfinish中处理在iframe中输出的数据。由于可能出现一些意外情况导致响应很久,甚至没有响应,所以一定要设置timeout以防万【处理返回数据】上面提到,可以在onfinish中处理在iframe中输出的数据。要从iframe的body中获取数据,有以下几个方法:讦 rame.contentwin

30、dow.document.body.in nerhtmliframe.contentdbody.i nn erhtml window.framesiframe name.document, body.in nerhtml 其屮前两种差不多,后者比较简便,但ie不支持contentdocument,可惜。 第三种是利用frames对象来获取,注意这样获取的对象直接就是window对象。 由于程序能直接获得iframe对象,所以用的是第一种方式。不过有一个问题在iframe的部分也提过,就是返回错误信息页面的问题。 在上传文件实例中,在iframe屮输岀的是json形式的文件信息数据。在onfin

31、ish中是这样处理的:复制代码代码如下:tryvar info = eval("(" + iframe.contentwindow.document.body.innerhtml + ")''); show(”上传完成“);catch(e)show("上传失败”);stop(); return;只有返回正确的json格式数据才能正常运行,否则就抛岀错误,间接地排除了 404等错误 信息。ps:有更好方法的话欢迎提出。【销毁程序】程序屮有不少dom操作,在不需要继续使用的时候最好执行一次dispose方法来销毁程序。 例如移除file之后,

32、关闭窗口之前,提交表单之前,历遍表单元素前等等。既可以节省资源,防止dom的内存泄漏,又能避免表单嵌套吋的冲突问题。【可用性】看过“ppk谈javascriptn后,更加注重了可用性。上传实例在浏览器不支持js的情况下也能正常上传,各位可以自行测试。【编码】 上一个无刷新上传系统,很多人反映上传后文件名乱码,后來发现是编码的问题。当有中文信息传递时,要注意前后台的编码必须统一,包括charset,文件编码,web.config 的配置等。asp版本】asp版本跟.net版本功能是一样的,使用无组件上传类。不过上传类本身有一个缺陷导致提交同名file控件的话会出错,经过修改后现在可以正常使 用了

33、。使用说明实例化时,第一个必要参数是file控件对象:new quickupload(file);第二个可选参数用来设置系统的默认属性,包插 属性:默认值说明parameter: ,参数对象 action:设置 action timeout: 0,/设置超时(秒为单位) onready: function(),/上传准备时执行 onfinish: function(),上传完成时执行 onstop: function(),/上传停止时执行 ontimeout: function()/上传超时时执行还提供了以下方法: upload:执行上传操作; stop:停止上传操作; dispose:销毁程

34、序。程序源码复制代码代码如下:var quickupload = function(file, options) this._sending = false;/ 是否正在上传this._timer = null;/定时器this.frame = null;/讦rame 对彖this._form = null;/form 对象this._inputs = ;/input 对象this._ffinish = null;/完成执行函数$.extend(this, this._setoptions(options);;quickupload._co un ter = 1;quickllpload.pr

35、ototype = 设置默认属性_setoptions: function(options) this.options = /默认值action:"”丿/设置 actiontimeout: 0,/设置超时(秒为单位)parameter: ,/参数对象onready: function(),/上传准备时执行onfinish: function(),上传完成时执行onstop: function(),/上传停止时执行ontimeout: function()/上传超时时执行;return $.extend(this.options, options 11 );,上传文件upload: f

36、unction() 停止上一次上传this.stop();没有文件返回if ( !this.file 11 !this.file.value ) return;可能在onready中修改相关属性所以放前面this.onready();设置iframe,form和表单控件this._setlframe();this._setform();this._setlnput();设置超时讦(this.timeout > 0 ) this._timer = settimeout( $f.bind(this._timeout, this), this.timeout * 1000 ); 开始上传thi

37、s._form.submit();this._sendi ng = true;,设置 iframe_setlframe: function() if ( !this._iframe ) 创建讦ramevar 讦ramename = "quickupload_" + quickllpload._counter+,iframe = document.createelement( $b.ie ? "<iframe name="" + iframename +: "iframe");iframe. name = iframen

38、ame;讦 rame.style.display = "none"记录完成程序方便移除var finish = this._ffinish = $f.bind(this._finish/ this);/iframe加载完后执行完成程序if($b.ie)if rame.attacheventf11 on load", finish ); else iframe.o nload = $b.opera ? function() this, on load = fin ish;: fin ish;插入bodyvar body = document.body; body.i

39、nsertbefore( iframe, body.childnodes0);this.frame = iframe;,设置form_setform: function() if ( !this._form ) var form = document.createelement('form'), file = this.file;设置属性$.extend(form, target: , method: "post", encoding: "multipart/form-data");设置样式$d.setsty

40、le(form, padding: 0, margin: 0, border: 0,backgroundcolor: "transparent”,display: "inline");提交前去掉formfile.form && $e.addevent(file.form, "submit", $f.bind(this.dispose, this);插入formfile.parentnode.insertbefore(form, file).appendchild(file);this, form = form;/action可能会修改this. form.action = this.action;,设置input_setlnput: function() var form = this._formz oldlnputs = this._inputs, newlnputs = , name; 设置inputfor ( name in this.parameter) var input = formname;讦(!input) 如果没有对应input新建一个in put = document.

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论