前言
由于讨厌各种上传插件和UI绑定,同样是为了自己练练手,我写了一个十分小巧的jQuery上传插件——JFile
[文档]()
提供的功能
- 多文件上传
- 中途取消
- 文件大小、类型限制设定
- 能取到进度(进度条UI可以自己定制哦)
- 可选的上传图片预览
- 类似于jQuery AJAX的调用风格
依赖
- 上传依赖于FormData和Level2的XHttpRequest(一般都支持)
- 预览依赖于HTML5的File API
- jQuery
使用
var jq=$('#input').upload(url,{
preview:true,
limits:{
fieldSize:40,
...
},
...
}).done(function(data,status,xhr){..})
.fail(function(xhr,status,err){..})
.always(function(xhr,status,err){..})
.progress(function(percentage){..});
jq.abort();
源代码
/**
* Created by suemi on 14-12-8.
*/
(function($){
$.fn.upload=function(url,settings){
var option={
method:'POST',
action:url,
dataType:'json',
limits:{},
preview:null
};
if(!settings) var settings={};
$.extend(option,settings);
var getXhr = function(){
var xhr;
return function(){
if (xhr) return xhr;
if (typeof XMLHttpRequest !== 'undefined') {
xhr = new XMLHttpRequest();
} else {
var v = [
"Microsoft.XmlHttp",
"MSXML2.XmlHttp.5.0",
"MSXML2.XmlHttp.4.0",
"MSXML2.XmlHttp.3.0",
"MSXML2.XmlHttp.2.0"
];
for (var i=0; i < v.length; i++){
try {
xhr = new ActiveXObject(v[i]);
break;
} catch (e){}
}
}
return xhr;
}
}();
function checkExtension(dst,src){
var tmp=dst.split('/');
if(tmp[0]=='image'){
if($.inArray('image/*',src)==-1){
if($.inArray(tmp[1],src)==-1) return false;
else return true;
}
else return true;
}
else{
if($.inArray(tmp[1],src)==-1) return false;
else return true;
}
}
var fileList=[];
$(this).each(function(){
for(var i=0;i<this.files.length;i++){
fileList.push(this.files[i]);
}
});
return $.Deferred(function(){
var xhr=getXhr();
var defer=this;
this.abort=function(){
if(xhr) xhr.abort();
return defer;
};
this.preview=function(tmp){
for(var i in fileList){
var file=fileList[i];
if(file.type.split('/')[0]=='image'){
if(!window.FileReader){
alert('Too old browser, you need a modern one!');
return defer;
}
var reader=new FileReader();
reader.name=file.name;
reader.onloadend=function(evt){
console.log(this.num);
if(reader.error) tmp.append($('<p>'+this.name+' fails to be loaded</p>'));
else tmp.append($('<img>',{'src':evt.target.result,'alt':this.name}));
};
reader.readAsDataURL(file);
}
else continue;
}
return defer;
};
if(window.FormData) var form=new FormData();
else{
// alert('Too old for your browser, get a modern one!');
this.reject(xhr,null,new Error('Too Old Browser'));
return this;
}
if(!xhr){
this.reject(xhr,null,new Error('Too Old Browser'));
return this;
}
if(!option.action){
this.reject(xhr,null,new Error('URL Needed'));
return this;
}
xhr.open(option.method,option.action);
xhr.upload.addEventListener('progress',function(evt){
if(evt.lengthComputable){
var complete=evt.loaded/evt.total | 0;
}
defer.notify(complete);
});
xhr.onreadystatechange=function(){
if(this.readyState!==4) return;
if(this.status==200){
var data;
switch(option.dataType){
case 'text':
data=this.responseText;
break;
case 'html':
data= $.parseHTML(this.responseText);
break;
case 'xml':
data= $.parseXML(this.responseXML);
break;
case 'json':
data= $.parseJSON(this.responseText);
break;
default :break;
}
defer.resolve(data,this.status,this);
}
else{
defer.reject(this,this.status,this.responseText);
}
};
if(fileList.length==0){
//defer.reject(xhr,xhr.status,new Error('No File Select'));
return defer;
}
if(option.limits.fieldSize&&option.limits.fieldSize<fileList.length){
var err=new Error('Too Many Files');
defer.reject(xhr,xhr.status,err);
return defer;
}
for(var i in fileList){
var file=fileList[i];
if(option.limits.validExtension&&!checkExtension(file.type,option.limits.validExtension)){
var err=new Error('File Type Error');
err.filename=file.name;
defer.reject(xhr,xhr.status,err);
continue;
}
if(option.limits.fileSize&&option.limits.fileSize<file.size){
var err=new Error('Too Large Size');
defer.reject(xhr,xhr.status,err);
return defer;
}
if(option.start) option.start(file);
form.append(i,file,file.name);
if(option.maxSize) option.maxSize-=file.size;
}
if(option.preview) this.preview(option.preview);
xhr.send(form);
return defer;
});
};
})(jQuery);