无刷新上传的方法很多,比如:
- 利用现代浏览器的FormData。
- 利用现代浏览器的FileReader将图片文件编程base64编码。
- 利用类库(如jQuery)的ajax。
- 利用iframe。
最近接到一个项目要求兼容IE8+,没有选择余地,只能用iframe了。原理如下:
这上述代码里,最重要得就是** target="file" **。它实现了使用隐藏的iframe上传文件。
这样,我们就可以在上传文件后返回给iframe结果,再用js解析iframe里的内容--或者是显示图片,或者是显示提示信息。
代码如下:
/**
* 利用隐藏iframe无刷新上传图片
* usage:
* var widget = new IframeUpload({
container:'.container',//上传的组件(带+号的div)要放在哪个类或者id里,隐藏的input也放在这里
uploadUrl:'upload.php',
deleteUrl:'delete.php',
deleteMethod:'post',//可以不写,默认是post
max:5//最多上传几张图片
});
* @type {Class}
*/
var IframeUpload = new Class({
count:0,//记录目前页面上存在的iframe
initialize:function(options){
var othis = this;
var defaultOptions = {
container:"file",
marginRight:10,//upload widget 间隔
className:'iframe-upload-widget',//给adopt进页面的form加一个类,最后删除
max:5,
interval:50,
ajaxName:'file',//iframe 上传图片时,图片的name
imageName:'file[]',//最后一次性上传图片时图片的name
uploadUrl:"upload.php",
method:'post',//upload method
deleteUrl:'',
deleteMethod:'post',
deleteTag:'id',//删除一张图片时,指定隐藏input的name
enctype:"multipart/form-data",
onSuccess:function(html){
//console.log(html)
// var othis = this.self;
var arr = html.split(";");
if(arr.length == 2){
this.appendImage(arr[0]);
this.setValue(arr[1]);
}else{
Dialog.alert(html);
}
}
};
if(typeOf(options) == "object"){
var opt = this.opt = Object.merge(defaultOptions,options);
}else{
var opt = this.opt = defaultOptions;
}
var classOrId = opt.container;
var first = classOrId.substring(0,1);
if(first == "."){
othis.container = $$(classOrId);
}else if(first == "#"){
alert("container can not start with #");
}else{
othis.container = $(classOrId);
}
othis.init();
},
init:function(){
this.createInput();
},
clear:function(){
var othis = this;
$$("."+othis.opt.className).dispose();
},
getIframeBody:function(iframe){
return iframe.contentWindow.document.body;
},
listen:function(iframe,input,wrap,tagIdInput){
var othis = this;
var opt = othis.opt;
var timeout = setInterval(function(){
var html = othis.getIframeBody(iframe).innerHTML.trim();
if(html != ""){
othis.getIframeBody(iframe).innerHTML = "";
clearInterval(timeout);
if(othis.count < opt.max){
othis.createInput();
}
opt.onSuccess.bind({
self:othis,
setValue:function(value){
input.set("value",value);
tagIdInput.set("value",value);
},
appendImage:function(imageUrl){
othis.appendImage(wrap,imageUrl);
},
input:input,
tagInput:tagIdInput,
div:wrap
})(html);
}
},opt.interval);
},
uuid:function(num){
var letters = ['a','b','c','d','e','f','g','h','i','1','2','3','4','5','6','7','8','9'];
if(typeOf(num) != "number"){
num = 8;
}
var code = "";
for(var i = 0;i+上传图片
",
events:{
'click':function(){
input.click();
},
},
});
form = new Element("form",{
action:opt.uploadUrl,
method:opt.method,
target:iframeName,
enctype:opt.enctype,
'class':opt.className,
styles:{
display:"none"
}
});
iframe = new Element("iframe",{
name:iframeName,
styles:{
display:'none'
}
});
tagIdInput = new Element("input",{
name:opt.deleteTag,
styles:{
display:'none',
}
});
//用于最后上传的input
hiddenInput = new Element("input",{
type:'hidden',
'data-index':1,
id:mapId,
name:opt.imageName,
});
if(othis.count > 1){
var deleteIcon = new Element("span",{
styles:{
position:"absolute",
right:-8,
top:-8,
borderRadius:'50%',
textAlign:'center',
lineHeight:18,
width:16,
height:16,
border:'1px solid #333',
backgroundColor:'#efefef',
color:'red',
cursor:'pointer',
},
html:'×',
events:{
click:function(e){
e.stop();
if(opt.deleteUrl){
var data = opt.deleteTag+"="+hiddenInput.get("value");
new Request({
url:opt.deleteUrl,
'data':data,
method:opt.deleteMethod
}).send();
}
hiddenInput.dispose();
wrap.dispose();
othis.count --;
}
}
});
wrap.adopt(deleteIcon);
}
form.adopt(input,iframe,tagIdInput);
$$(document.body).adopt(form);
othis.container.adopt(wrap,hiddenInput);
},
});
后端php对应的代码:
#file upload.php