文件上传很常见,也有好些方法,不过我见过的大多是基于flash的,也有用XMLhttpResponse来提交文件的,其实大可不必这么麻烦,我这里介绍一种更具兼容性的用法,利用iframe来曲线实现无刷新页面文件上传功能,这种方法其实也很常见了。
iframe上传文件原理是这样的:首先input file控件本身是被表单包含的,表单属性必须设置为enctype="multipart/form-data",才能上传任意文件。但是仅仅有这个还不行, 因为提交表单后,它会自动刷新页面,为了不让它离开本页,我们可以在这个提交的页面上动态生成一个隐藏的iframe,但是别忘了在表单上再添加一个属性target,并且指定为iframe的name,这样表单提交后,服务器才会将返回的结果会写在iframe里。最后在从这个iframe里获取数据就可以了。
原理上不难理解,也不难实现。在这上面还可以扩展出更多的功能,比如上传前判断文件类型,大小之类的,添加一个加载的过程等等。不过在实现的过程,还是遇到了几个难点:一个是获取文件信息,这个在不同的浏览器上,获取的方法不尽相同;另外一个是获取iframe里的内容。这些问题的解决方法,我没有很好的解决,不过貌似也没有什么大问题,所以我把解决的方法写在这里。
获取文件信息:我这里只是实现了获取文件名称的功能。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
1getFile:
function
() {
2
var
fileInfo = {};
3
var
isIE = !!window.ActiveXObject;
4
//var isIE6 = isIE&&!window.XMLHttpRequest;
5
//var isIE8 = isIE&&!!document.documentMode;
6
//var isIE7 = isIE&&!isIE6&&!isIE8;
7
var
path =
''
;
8if(isIE) {
9path = document.getElementById(
this
.config.id).value;
10fileInfo.fileName = path.slice(path.lastIndexOf(
'\\'
)+
1
);
11
} elsefileInfo.fileName = document.getElementById(
this
.config.id).files[
0
].name;
12returnfileInfo;
13
}
|
获取iframe的内容:
1
|
document.getElementById(
"iframe"
).find(
'body'
).html();
|
我这里先展示一个基本的上传代码,供各位参考。 我这个是不带界面的,纯逻辑部分。页面须有个<input type='file' id='uploader' name='file'/>标签,然后可以这样调用:
1
2
3
4
5
6
|
var
uploader = newFileUploader({
action:
'url'
,
//上传地址
onChange:
function
() {},
//上传前
loading:
function
() {},
//上传过程中
onComplete:
function
() {}
//上传完成后
}) ;
|
点击按钮选择一个文件后就会立即提交。
完整代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
1functionFileUploader(config) {
2this.config = config;
3this.input = $(
'#'
+
this
.config.id);
4this.action =
this
.config.action ||
''
;
5this.method =
this
.config.method ||
'post'
;
6this.type =
this
.config.type ||
'json'
;
7this.init();
8
}
9FileUploader.prototype = {
10init:
function
() {
11
var
that =
this
;
12this.addListener(
'change'
,
function
() {
13if(that.config.onChange) {
14
var
res =
false
;
15res = that.config.onChange.call(
this
, that.getFile());
16if(!res) returnfalse;
17
}
18that.load();
19
});
20
},
21load:
function
() {
22
var
that =
this
;
23this.wrap();
24this.send();
25if(that.config.loading) that.config.loading.call(that);
26
$(
'iframe'
).bind(
'load'
,
function
() {
27
var
data = that.getResponse(document.getElementById(
"hidden_frame"
)).find(
'body'
).html();
28data = data.replace(/<pre.*>(.*)<\/pre>/,
"$1"
);
29if(that.config.onComplete) {
30if(that.type ==
'json'
) data = eval(
'('
+data+
')'
);
31that.config.onComplete.call(
this
, data, that.input);
32
}
33
//this.input.unwrap();
34
$(
this
).remove();
35
});
36
},
37getResponse:
function
(iframe) {
38
var
doc = $(iframe).contents();
39returndoc;
40
},
41remove:
function
() {
42this.input.remove();
43
},
44getFile:
function
() {
45
var
fileInfo = {};
46
var
isIE = !!window.ActiveXObject;
47
var
isIE6 = isIE&&!window.XMLHttpRequest;
48
var
isIE8 = isIE&&!!document.documentMode;
49
var
isIE7 = isIE&&!isIE6&&!isIE8;
50
var
path =
''
;
51if(isIE) {
52path = document.getElementById(
this
.config.id).value;
53fileInfo.fileName = path.slice(path.lastIndexOf(
'\\'
)+
1
);
54
} elsefileInfo.fileName = document.getElementById(
this
.config.id).files[
0
].name;
55returnfileInfo;
56
},
57send:
function
(cb) {
58
var
that =
this
;
59this.input.parent(
'form'
).submit();
60
},
61wrap:
function
() {
62this.input.wrap(
63
'<form enctype="multipart/form-data"'
+
64
'action="'
+
this
.action+
'" method="'
+
this
.method+
'" target="hidden_frame">'
+
65
'</form>'
66
);
67this.input.parent(
'form'
).after(
68
'<iframe name="hidden_frame" id="hidden_frame" src="javascript:false;" ></iframe>'
69
);
70
},
71addListener:
function
(type, cb) {
72if(type ==
'change'
)
this
.input.bind(
'change'
, cb);
73
}
74
};
|