|
|
4#

楼主 |
发表于 2009-12-3 14:16:53
|
只看该作者

使用技巧
【上传文件数】
在文件上传实例中,各个文件是同时上传的。
经测试,浏览器能同时上传的文件数如下:
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:有更好方法的话欢迎提出。
【移除程序】
程序中有不少dom操作,在不需要继续使用的时候最好执行一次remove方法来移除程序。例如移除file之后,关闭窗口之前,提交表单之前,历遍表单元素前等等。既可以节省资源,防止dom的内存泄漏,又能避免表单嵌套时的冲突问题。
【可用性】
看过“ppk谈javascript”后,更加注重了可用性。上传实例在浏览器不支持js的情况下也能正常上传,各位可以自行测试。
【编码】
上一个无刷新上传系统,很多人反映上传后文件名乱码,后来发现是编码的问题。当有中文信息传递时,要注意前后台的编码必须统一,包括charset,文件编码,web.config的配置等。
【asp版本】
asp版本跟.net版本功能是一样的,使用无组件上传类。不过上传类本身有一个缺陷导致提交同名file控件的话会出错,经过修改后现在可以正常使用了。
使用说明
实例化时,第一个必要参数是file控件对象:new QuickUpload(file);
第二个可选参数用来设置系统的默认属性,包括
属性: 默认值//说明
parameter: {},//参数对象
action: "",//设置action
timeout: 0,//设置超时(秒为单位)
onReady: function(){},//上传准备时执行
onFinish: function(){},//上传完成时执行
onStop: function(){},//上传停止时执行
onTimeout: function(){}//上传超时时执行
还提供了以下方法:
upload:执行上传操作;
stop:停止上传操作;
remove:清除程序。
程序源码
var QuickUpload = function(file, options) {
this.file = $$(file);
this._sending = false;//是否正在上传
this._timer = null;//定时器
this._iframe = null;//iframe对象
this._form = null;//form对象
this._inputs = {};//input对象
this._fFINISH = null;//完成执行函数
$$.extend(this, this._setOptions(options));
};
QuickUpload._counter = 1;
QuickUpload.prototype = {
//设置默认属性
_setOptions: function(options) {
this.options = {//默认值
action: "",//设置action
timeout: 0,//设置超时(秒为单位)
parameter: {},//参数对象
onReady: function(){},//上传准备时执行
onFinish: function(){},//上传完成时执行
onStop: function(){},//上传停止时执行
onTimeout: function(){}//上传超时时执行
};
return $$.extend(this.options, options || {});
},
//上传文件
upload: function() {
//停止上一次上传
this.stop();
//没有文件返回
if ( !this.file || !this.file.value ) return;
//可能在onReady中修改相关属性所以放前面
this.onReady();
//设置iframe,form和表单控件
this._setIframe();
this._setForm();
this._setInput();
//设置超时
if ( this.timeout > 0 ) {
this._timer = setTimeout( $$F.bind(this._timeout, this), this.timeout * 1000 );
}
//开始上传
this._form.submit();
this._sending = true;
},
//设置iframe
_setIframe: function() {
if ( !this._iframe ) {
//创建iframe
var iframename = "QUICKUPLOAD_" + QuickUpload._counter++,
iframe = document.createElement( $$B.ie ? "<iframe name=\"" + iframename + "\">" : "iframe");
iframe.name = iframename;
iframe.style.display = "none";
//记录完成程序方便移除
var finish = this._fFINISH = $$F.bind(this._finish, this);
//iframe加载完后执行完成程序
if ( $$B.ie ) {
iframe.attachEvent( "onload", finish );
} else {
iframe.onload = $$B.opera ? function(){ this.onload = finish; } : finish;
}
//插入body
var body = document.body; body.insertBefore( iframe, body.childNodes[0] );
this._iframe = iframe;
}
},
//设置form
_setForm: function() {
if ( !this._form ) {
var form = document.createElement('form'), file = this.file;
//设置属性
$$.extend(form, {
target: this._iframe.name, method: "post", encoding: "multipart/form-data"
});
//设置样式
$$D.setStyle(form, {
padding: 0, margin: 0, border: 0,
backgroundColor: "transparent", display: "inline"
});
//提交前去掉form
file.form && $$E.addEvent(file.form, "submit", $$F.bind(this.remove, this));
//插入form
file.parentNode.insertBefore(form, file).appendChild(file);
this._form = form;
}
//action可能会修改
this._form.action = this.action;
},
//设置input
_setInput: function() {
var form = this._form, oldInputs = this._inputs, newInputs = {}, name;
//设置input
for ( name in this.parameter ) {
var input = form[name];
if ( !input ) {
//如果没有对应input新建一个
input = document.createElement("input");
input.name = name; input.type = "hidden";
form.appendChild(input);
}
input.value = this.parameter[name];
//记录当前input
newInputs[name] = input;
//删除已有记录
delete oldInputs[name];
}
//移除无用input
for ( name in oldInputs ) { form.removeChild( oldInputs[name] ); }
//保存当前input
this._inputs = newInputs;
},
//停止上传
stop: function() {
if ( this._sending ) {
this._sending = false;
clearTimeout(this._timer);
//重置iframe
if ( $$B.opera ) {//opera通过设置src会有问题
this._removeIframe();
} else {
this._iframe.src = "";
}
this.onStop();
}
},
//清除程序
remove: function() {
this._sending = false;
clearTimeout(this._timer);
//清除iframe
if ( $$B.firefox ) {
setTimeout($$F.bind(this._removeIframe, this), 0);
} else {
this._removeIframe();
}
//清除form
this._removeForm();
//清除dom关联
this._inputs = this._fFINISH = this.file = null;
},
//清除iframe
_removeIframe: function() {
if ( this._iframe ) {
var iframe = this._iframe;
$$B.ie ? iframe.detachEvent( "onload", this._fFINISH ) : ( iframe.onload = null );
document.body.removeChild(iframe); this._iframe = null;
}
},
//清除form
_removeForm: function() {
if ( this._form ) {
var form = this._form, parent = form.parentNode;
if ( parent ) {
parent.insertBefore(this.file, form); parent.removeChild(form);
}
this._form = this._inputs = null;
}
},
//超时函数
_timeout: function() {
if ( this._sending ) { this._sending = false; this.stop(); this.onTimeout(); }
},
//完成函数
_finish: function() {
if ( this._sending ) { this._sending = false; this.onFinish(this._iframe); }
}
}
完整实例下载
完整实例下载(asp版本) |
|