建站学 - 轻松建站从此开始!

建站学-个人建站指南,网页制作,网站设计,网站制作教程

简便无刷新文件上传系统(2)

时间:2009-12-01 22:06来源: 作者: 点击:
【input】 如果有其他参数要传递,程序会使用_setInput函数来创建传递数据的表单控件。 由于生成的form里面只有file控件,要传递其他参数只能用程序生成了。 程序用一个_inputs集合来保存当前在form中生成的表单控


【input】

如果有其他参数要传递,程序会使用_setInput函数来创建传递数据的表单控件。

由于生成的form里面只有file控件,要传递其他参数只能用程序生成了。
程序用一个_inputs集合来保存当前在form中生成的表单控件。

首先根据自定义的parameter属性创建表单控件:

Code


当form中没有对应name的控件时,会自动生成一个hidden控件插入到form中。
其中newInputs是用来记录当前生成的控件的,而oldInputs就是_inputs集合。
当设置过对应name的控件后,就从oldInputs中删除对应控件的关联。

然后移除oldInputs关联的控件:

for ( name in oldInputs ) { form.removeChild( oldInputs[name] ); }

这样就能移除上一次生成的无用的控件了。

最后重新记录当前控件到_inputs方便下次使用。


【stop】

如果想停止当前上传操作,可以调用stop方法。

一般来说当iframe发生重载时,会取消上一次的载入,那么只要重新设置src就能取消上传了。
测试以下代码:

Code


结果都能取消加载,除了opera,未知什么原因。
有两个方法解决,一个是通过form随便用一个action提交一次,还有就是直接移除iframe。
后一个方法比较方便,程序中用_removeIframe方法直接移除iframe。
ps:有更好方法的话记得告诉我。


【remove】

当使用结束或其他原因要清除程序时,可以调用remove方法。

remove里面主要做的是清除iframe和form。
清除iframe用的是_removeIframe方法,首先把onload移除,再把iframe从body移除:

var iframe = this._iframe;
$$B.ie 
? iframe.detachEvent( "onload"this._fFINISH ) : ( iframe.onload = null );
document.body.removeChild(iframe); 
this._iframe = null;

十分简单,但在ff有一个问题,测试以下代码:


<form target="ifr" action="x">
    
<input id="btn" type="submit" value="click">
</form>
<iframe name="ifr" id="ifr"></iframe>
<script>
document.getElementById(
"btn").onclick = function(){
    document.getElementById(
"ifr").onload = function(){
        
this.parentNode.removeChild(this);
    };
}
</script>


提交后都能移除iframe,但ff还一直显示“载入中”的状态。
不过解决方法也很简单,用setTimeout设置一个延时,让iframe执行完整就可以了。
所以在remove中是这样调用_removeIframe的:

if ( $$B.firefox ) {
    setTimeout($$F.bind(
this._removeIframe, this), 0);
else {
    
this._removeIframe();
}


至于form的清除就比较简单,在_removeForm这样处理:

var form = this._form, parent = form.parentNode;
if ( parent ) {
    parent.insertBefore(
this.file, form); parent.removeChild(form);
}
this._form = this._inputs = null;


要判断一下parentNode,否则如果parentNode不存在的话后面的会执行出错。


【file的reset】

在实例里,有一个用来重置file控件的ResetFile函数。

重置file控件一般的办法是使所在的form执行reset,但问题是会把其他表单控件也重置了。
以前由于安全问题,file的value是不允许修改的。
但现在ff,chrome和safari可以把它设为空值来实现重置:

file.value = "";

当然其他值还是不允许的。
ps:记忆中以前是不行的,不知有没有记错。

对于opera,有一个变通的方法,利用它的type属性:

file.type = "text"; file.type = "file";

通过修改type得到的file控件,value会自动还原成空值,这样就间接把file控件清空了。
ps:利用这个方法可以间接得到文件路径,但由于变回去后值就清空了,所以没什么用。

而ie的表单控件的type设置后是不允许修改的,不能用opera的办法。
不过还是有以下方法解决:
1,新建一个form,把file插进入后reset,再移除:

with(file.parentNode.insertBefore(document.createElement('form'), file)){
    appendChild(file); reset(); removeNode(
false);
}

好处是使用原生的reset,稳定可靠,但效率低。
ps:removeNode只有ie和opera支持,如需兼容可改用removeChild的方式。

2,利用outerHTML,重建一个file控件:

file.outerHTML = file.outerHTML;

好处是高效,但由于是新创建的file控件,之前关联的东西都丢失了。
ps:ff支持不支持outerHTML。

3,利用cloneNode,复制一个file控件:

file.parentNode.replaceChild(file.cloneNode(false), file);

跟上一个方法差不多,但效率更低。

4,利用select方法选中file控件的文本域,再进行清空:

file.select(); document.selection.clear();

file.select(); document.selection.clear();

基本没有问题,但file必须能被select(不能是隐藏状态)。
ps:这两个方法都只能在ie使用。

由于程序中file是需要关联的,所以方法2和3都不能用。
方法4貌似也不错,但有一个致命问题,在ie测试以下代码:

Code


执行到submit会显示“拒绝访问”的错误,看来ie早就猜到这种“诡计”不允许这样操作了。

看来也只能使用方法1了:

Code

ps:有更好方法的话记得告诉我啊。

这个函数并不够通用,最好还是根据实际情况选择需要的方法。


使用技巧

【上传文件数】

在文件上传实例中,各个文件是同时上传的。
经测试,浏览器能同时上传的文件数如下:
ie 2
ff 8
opera 8
chrome 6
safari 6
由于ie最多同时只能传2个,所以设置更多文件也只能排队,而不能达到同时上传的效果的。
ps:测试不太专业,可能有错。

【传递参数】

上传文件实例中,可以传递对应的修改文件名,在使用“一般上传”多个文件一起上传时也能找到对应的文件名。
因为表单控件值传递到后台后,获取数据的顺序跟前台表单控件的排列顺序是一致的。
只要保证前台file控件跟对应表单控件的排列顺序一致就能利用这个特性获取对应的值了。
详细参考后台代码。

【回调函数】

有两个方法可以响应上传完成回调函数。
一种是后台上传完成后,在iframe输出并执行回调函数或通过parent调用父窗口的回调函数。
这种比较方便,但必须在iframe里面执行处理,例如文件属性查看实例。
另一种是在iframe的onload中执行回调函数。
好处是可以把所有处理放在父窗口,iframe可以不做任何处理或用来反馈信息。
缺点是有兼容性问题,而且会有加载后没有触发onload的情况(上面的iframe部分有说明)。
上传文件实例中就是在onFinish中处理在iframe中输出的数据。
由于可能出现一些意外情况导致响应很久,甚至没有响应,所以一定要设置timeout以防万一。

【处理返回数据】

上面提到,可以在onFinish中处理在iframe中输出的数据。
要从iframe的body中获取数据,有以下几个方法:
iframe.contentWindow.document.body.innerHTML
iframe.contentDocument.body.innerHTML
window.frames[iframename].document.body.innerHTML
其中前两种差不多,后者比较简便,但ie不支持contentDocument,可惜。
第三种是利用frames对象来获取,注意这样获取的对象直接就是window对象。
由于程序能直接获得iframe对象,所以用的是第一种方式。
不过有一个问题在iframe的部分也提过,就是返回错误信息页面的问题。
在上传文件实例中,在iframe中输出的是json形式的文件信息数据。
在onFinish中是这样处理的:

try{
    
var info = eval("(" + iframe.contentWindow.document.body.innerHTML + ")");
    show(
"上传完成");
}
catch(e){
    show(
"上传失败"); stop(); return;
}

只有返回正确的json格式数据才能正常运行,否则就抛出错误,间接地排除了404等错误信息。
ps:有更好方法的话欢迎提出。

(责任编辑:admin)
织梦二维码生成器
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片