先说说为啥要扩展?
webupload是百度团队开源的一块非常优秀的上传插件提供分片、并发、压缩等(http://fex.baidu.com/webuploader/),不提供界面ui需要用户自己设计界面。我的需求是一个页面需要动态创建多个webupload对象,这就造成了页面需要写n多行dom操作代码。清除对象时需要预先用全局变量存储动态创建的对象,这代码写着写着就变臃肿了,所以就扩展成一个jquery插件的形式。
先来点效果再上代码,没精力折腾了,敲完撤。
代码有css js 和图片 css当然是拷贝抄袭精简别人的了
ext-webuploader.js
/**
* webUpload扩展
*/
;(function($,$window) {
//定义全局类
var UploadExt = $window.UploadExt ||{
extList:{}//extObj对象集合
};
$window.UploadExt = UploadExt;
//定义ExtObj类构造器
function ExtObj(id,opt){
this.id=id,
this.defaults = {
id:"", //当前上传容器唯一标示
name:"", //文件上传成功后文件路径接收域name值
pathValues:"", //文件路径
type:"file", //类型 file 或是 image,默认 file
readOnly:false, //是否只读, 只读不显示选择文件按钮,只显示 pathValues对应的文件
auto:false, //是否自动上传
params:"", //这是上传时需要传递的参数,拼接url后面多个参数以&分隔
extendParams:{}, //这是每个文件上传时候需要传递的参数,类似 css 写法
buttonStyle:"btn-green btn-S", //按钮颜色和大小 默认-绿色小号
fileNumLimit:3, //上传最大文件数
fileSingleSizeLimit:5*1024*1024,//单个文件大小限制(单位- [B])
duplicate:true, //去重, 根据文件名字、文件大小和最后修改时间来生成 hash Key
extensions:null, //认许文件后缀名
buttonText:"选择文件", //控件按钮显示文本
fileVal:"file", //文件上传域的name值
url:"webUpload.do", //上传url
downloadUrl:"webDownload.do?dbPath=",//默认下载地址
onSuccess:function(file,response){}, //上传成功后的回调函数
},
this.options = $.extend({}, this.defaults, opt);
}
/**
* 添加 获取/构建 extObj对象
*/
UploadExt.getExtObj = function(id,opt){
var obj = this.extList[id];
if (!obj && opt) {//不存在则通过参数创建对象
//不存在则通过jquery插件方法构造extObj对象
obj = extList[id] =$("#"+id).extWebUploader(opt);
}
return obj;
};
/**
* 销毁百度webupload上传对象
*/
UploadExt.destroy = function(id){
var obj = this.extList[id];
if (obj) {
obj.uploader.destroy();
delete this.extList[id];
}
};
//扩展jquery元素方法
$.fn.extWebUploader = function(opt,paramObj) {
Array.prototype.removeItem = function(val) {//给array对象添加方法
var index = this.indexOf(val);
if (index > -1) {
this.splice(index, 1);
}
};
//缩略图大小暂时写死,也可以修改css
var ratio = $window.devicePixelRatio || 1;
var thumbnailWidth = 100 * ratio;
var thumbnailHeight = 100 * ratio;
//随机数
var randomFor = function(n) {
var rnd = '';
for (var i = 0; i < n; i++) {
rnd += Math.floor(Math.random() * 10);
}
return rnd;
};
/**
* 检测是否支持base64
*/
var isSupportBase64 = function() {
var data = new Image();
var support = true;
data.onload = data.onerror = function() {
if (this.width != 1 || this.height != 1) {
support = false;
}
}
return support;
};
var getHtml = function(type,id,name,size){
var html1="<div class='dz-preview' id='"+id+"' >";
var html2img=" <div class='img-details'>";
var html2file=" <div class='file-details'>";
var html3="" +
" <div class='dz-filename'>"+
" <span>"+ name +"</span>"+
" </div>"+
" <div class='dz-size' data-dz-size=''>"+
"" + size +
" </div> ";
var html4=" <img src='' />";
var html5="" +
" <div class='dz-progress' style='display:block;'>"+
" <div class='progress'>"+
" <div class='progress-bar progress-bar-success progress-bar-striped active' role='progressbar' " +
" aria-valuenow='0' aria-valuemin='0' aria-valuemax='100' style='width:0%'></div>"+
" </div>"+
" </div>"+
" <div class='dz-error-message'>"+
" <span data-dz-errormessage=''></span>"+
" </div>"+
" </div>"+
" <div class='dz-success-mark'></div>"+
" <div class='dz-error-mark'></div> "+
" <div class='del-btn' data-path=''>删除</div>"+
"</div>";
var img_preview = html1 + html2img + html3 + html4 + html5;
var file_preview= html1 + html2file + html3 + html5;
if(type=="image"){
return img_preview;
}else{
return file_preview;
}
};
//换算大小值
var getSize = function(size){
if(size>1024*1024*1024){
var val = Math.round((size/(1024*1024*1024))*100)/100;
return "<strong>"+val+"</strong> GB";
}else if(size>1024*1024){
var val = Math.round((size/(1024*1024))*100)/100;
return "<strong>"+val+"</strong> MB";
}else if(size>1024){
var val = Math.round((size/1024)*100)/100;
return "<strong>"+val+"</strong> KB";
}else if(size>1024){
var val = Math.round(size*100)/100;
return "<strong>"+val+"</strong> B";
}else{
return "<strong>---</strong>";
}
};
//拆分文件名
var mygetFileName = function(filepath) {
if (filepath.lastIndexOf('\\') > 0) {
return filepath.substring(filepath.lastIndexOf('\\') + 1);
} else if (filepath.lastIndexOf('/') > 0) {
return filepath.substring(filepath.lastIndexOf('/') + 1);
} else {
return filepath;
}
};
//初始化jquery元素集,return方便链式调用
return this.each(function() {
var oo = $(this);
var ooId=oo.attr("id");//获取当前容器id
var extObj;
//显示上传图片
var showImg = function(src, id) {
if (extObj.options['type']=="image") {
$("#"+extObj.options['id']+id+" .img-details img").attr("src",src);
}
};
//添加文件dom
var addFileDom = function(file) {
var $list = $('#'+extObj.options['id']+'_thelist');
var id = extObj.options['id'] + file.id;
var name = file.name;
var size = file.size;
if(extObj.options['fileNumLimit']==1){
oo.prepend(getHtml(extObj.options['type'],id,name,size));
}else{//多个文件
$list.append(getHtml(extObj.options['type'],id,name,size));
}
//绑定删除事件
$("#"+extObj.options['id'] + file.id +" .del-btn").on('click',function() {
var optpath = $("#"+extObj.options['id'] + file.id +" .del-btn").attr("data-path");
if(optpath){
$.post('webUpload.do',{path:optpath,isdel: "1"},function(data) {
if (data.success) {
extObj['exsitPathArr'].removeItem(optpath);
$("#"+extObj.options['id'] + file.id).remove();//删除dom
$name = $('#'+extObj.options['id'] + " .fordel input[name='"+extObj.options['name']+"']");
if ($name.length) {
$name.val(extObj['exsitPathArr'].join(","));
}
if(file.type){
extObj['uploader'].removeFile(file.id);//移除文件
}
}
},'JSON');
}else{
$("#"+extObj.options['id'] + file.id).remove();//删除dom
extObj['uploader'].removeFile(file.id);//移除文件
if(file.type){
extObj['uploader'].removeFile(file.id);//移除文件
}
}
});
// //绑定下载事件
// $("#"+extObj.options['id'] + file.id +" .down-btn").on('click',function() {
// var optpath = $('#'+extObj.options['id'] + file.id + " input[name='"+extObj.options['name']+"']").val();
// if(optpath){
// var downsrc = extObj.options['downloadUrl'] + optpath + '&down=1';
// location.href = downsrc;
// }
// }
};
//先判断对象是否初始化过
if(UploadExt.extList[ooId]){
extObj = UploadExt.extList[ooId];
//调用对应方法
if("getObj"==opt){
return extObj.extWebUploader;
}else if("addFile"==opt){
//先判断是否超过数量限制
var num = $("#"+ooId+" DIV.dz-preview").length;
if(num >= extObj.options['fileNumLimit']){
tip('文件数量超标');
return extObj.extWebUploader;
}
//第二个参数对象为{path:'/test/stsets/abc.zip'}
var path = paramObj.path.replace("\\","\\\\");
extObj['exsitPathArr'].push(path);//将已存在的路径添加到数组中
$name = $('#'+ooId + " .fordel input[name='"+extObj.options['name']+"']");
if (!$name.length) {
oo.append( '<div class=\"fordel\"><input type=\"hidden\" name=\"'+extObj.options['name']+'\" value=\"'+path+'\" /></div>' );
}else{
$name.val(extObj['exsitPathArr'].join(","));
}
var singleSrc=extObj.options['downloadUrl']+path;
var objFile = new Object();
var sizeMatch=paramObj.size.match(/^\d+\.\d+/);
var size=paramObj.size.replace(sizeMatch[1],"<strong>"+sizeMatch[1]+"</strong>");
objFile['id']=randomFor(6);
objFile['name']=mygetFileName(singleSrc);
objFile['size']=size;
objFile['Status']='complete';//设置状态为上传完成
addFileDom(objFile);
showImg(singleSrc,objFile['id']);
$('#'+extObj.options['id'] + objFile['id']).addClass("dz-success");
}
}else{//初始化 构建extObj对象
var extObj =new ExtObj(ooId,opt);//oo表示当前操作jquery元素对象
extObj.options['id']= ooId;
UploadExt.extList[ooId]=extObj;//将extObj存储在list中
if(extObj.options['fileNumLimit']>1){//上传多个文件,增加list容器
oo.append(" <div id=\""+extObj.options['id']+"_thelist\" class=\"uploader-list\"></div>");
}
oo.append(" <div class=\"btns\">" +
" <div id=\""+extObj.options['id']+"_pick\">"+extObj.options['buttonText']+"</div>" +
" </div>");
//初始化webupload上传组件
var uploader = WebUploader.create({
swf: '/plug-in/webuploader/Uploader.swf',
server: extObj.options['url']+"?"+extObj.options['params'],
pick: '#'+extObj.options['id']+"_pick",
duplicate: extObj.options['duplicate'],
resize: false,
auto: extObj.options['auto'],
fileVal: extObj.options['fileVal'],
fileNumLimit: extObj.options['fileNumLimit'],
fileSingleSizeLimit: extObj.options['fileSingleSizeLimit'],
formData: extObj.options['extendParams'],
accept:{
extensions:extObj.options['extensions']
}
});
//添加对象属性 webupload对象
extObj['uploader'] =uploader;
extObj['extWebUploader']=this;//jquery对象extWebUploader
extObj['exsitPathArr']= new Array();//用户存储上传成功的路径数组
//增加按钮样式
$('#'+extObj.options['id']+"_pick").find('div:eq(0)').addClass('webuploader-pick '+extObj.options['buttonStyle']);
//手动上传
if(!extObj.options['auto']){
$('#'+extObj.options['id']+"_pick").find('div:eq(0)').after("<div id='"+extObj.options['id']+"ctlBtn' class='upbtn btn-blue "+extObj.options['buttonStyle']+"'>开始上传</div>");
var state = 'pending';//上传状态、当前等待状态
var $btn=$("#"+extObj.options['id']+"ctlBtn");
$btn.on('click', function (){
if (state === 'uploading'){
uploader.stop();
} else {
uploader.upload();
}
});
uploader.on('all',function (type){
if (type === 'startUpload'){
state = 'uploading';
$btn.text('暂停上传');
}else if (type === 'stopUpload'){
state = 'paused';
$btn.text('开始上传');
} else if (type === 'uploadFinished'){
state = 'done';
$btn.text('开始上传');
}
});
}
if(extObj.options['readOnly'] || extObj.options['readOnly'] == "readOnly"){
$("#"+extObj.options['id']+"ctlBtn").css('display','none');//隐藏开始上传
$("#"+extObj.options['id']+"_pick").css('display','none');//隐藏选择文件按钮
}
var addFile = function(file, filepath) {
uploader.makeThumb(file,
function(error, src) {
if (error) {
return false;
}
if (isSupportBase64()) {
if (filepath == '') {
showImg(src, file.id);
}
} else if (filepath != '') {
var actSrc = extObj.options['downloadUrl'] + filepath;
showImg(actSrc, file.id);
}
},thumbnailWidth, thumbnailHeight);
};
//设置默认值
if(null!=extObj.options['pathValues'] && extObj.options['pathValues'] !="" ){
var pvs = extObj.options['pathValues'].replace("\\","\\\\");
oo.append( '<div class=\"fordel\"><input type=\"hidden\" name=\"'+extObj.options['name']+'\" value=\"'+pvs+'\" /></div>' );
extObj['exsitPathArr']=pvs.split(',');//将默认值按逗号拆分添加到数组中
for(var a = 0; a< extObj['exsitPathArr'].length; a++){
var singlePath=extObj['exsitPathArr'][a];
if(''!=singlePath){
var singleSrc=extObj.options['downloadUrl']+singlePath;
var objFile = new Object();
objFile['id']=a;
objFile['name']=mygetFileName(singlePath);
objFile['Status']='complete';//设置状态为上传完成
objFile['size']="未知";
addFileDom(objFile);
showImg(singleSrc,objFile['id']);
$("#"+extObj.options['id'] + objFile['id'] +" .del-btn").attr("data-path",singlePath);//添加文件路径
$('#'+extObj.options['id'] + objFile['id']).addClass("dz-success");
}
}
}
//当文件被加入队列之前触发
uploader.on('beforeFileQueued',function(file) {
var num = $("#"+extObj.options['id']+" DIV.dz-preview").length;
if(num >= extObj.options['fileNumLimit']){
tip('文件数量超标');
return false;
}
return true;
});
//当文件被加入队列以后触发
uploader.on('fileQueued',function(file) {
file.size=getSize(file.size);//将size转换
addFileDom(file);
addFile(file,"");
});
//上传过程中触发,携带上传进度
uploader.on('uploadProgress',function(file, percentage) {
var $div = $('#'+extObj.options['id']+ file.id),
$percent = $div.find('.progress .progress-bar');
$percent.css('width', parseInt(percentage * 100)+'%');
$percent.attr("aria-valuenow",parseInt(percentage * 100));
});
//当文件上传成功时触发
uploader.on('uploadSuccess',function(file, response) {
if (response.success) {
var filepath = response[""+extObj.options['name']+""] || response.obj;
extObj['exsitPathArr'].push(filepath);//上传车成功后添加到数组中
$name = $('#'+extObj.options['id'] + " .fordel input[name='"+extObj.options['name']+"']");
if (!$name.length) {
oo.append( '<div class=\"fordel\"><input type=\"hidden\" name=\"'+extObj.options['name']+'\" value=\"'+filepath+'\" /></div>' );
}else{
$name.val(extObj['exsitPathArr'].join(","));
}
addFile(file, filepath);//如果是图片显示对应图片
$('#'+extObj.options['id'] + file.id).addClass("dz-success");
$("#"+extObj.options['id'] + file.id +" .del-btn").attr("data-path",filepath);//添加文件路径
} else {
$('#'+extObj.options['id'] + file.id).addClass("dz-error");
var errorMsg = $('#'+extObj.options['id'] + file.id+" .dz-error-message span");
errorMsg.html("上传出错" + response.msg);
errorMsg.data("dz-errormessage","上传出错" + response.msg);
}
extObj.options.onSuccess(file, response);
});
uploader.on('uploadError', function(file, reason) {
$('#'+extObj.options['id'] + file.id).addClass("dz-error");
var errorMsg = $('#'+extObj.options['id'] + file.id+" .dz-error-message span");
errorMsg.html("上传出错-code:" + reason);
errorMsg.data("dz-errormessage","上传出错-code:" + reason);
});
uploader.on('error',function(type) {
if (type == 'Q_TYPE_DENIED') {
$window.tip('文件类型不识别');
}
if (type == 'Q_EXCEED_NUM_LIMIT') {
$window.tip('文件数量超标');
}
if (type == 'F_DUPLICATE') {
$window.tip('相同文件请不要重复上传');
}
if (type == 'F_EXCEED_SIZE') {
$window.tip('单个文件大小超标');
}
if (type == 'Q_EXCEED_SIZE_LIMIT') {
$window.tip('文件大小超标');
}
});
uploader.on('uploadComplete',function(file) {
var $div = $('#'+extObj.options['id']+ file.id).find('.dz-progress');
$div.fadeOut('slow');
});
}
});
};
})(jQuery,window);
ext-webuploader.css
.dz-preview * {box-sizing: border-box;}
.dz-preview{
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.16);
font-size: 14px;
background: rgba(255, 255, 255, 0.8) none repeat scroll 0 0;
border: 1px solid #acacac;
display: inline-block;
padding: 6px;
position: relative;
}
.dz-preview.file-preview{display:block;}
.dz-preview .img-details,.dz-preview .file-details{
background: #ebebeb none repeat scroll 0 0;
height: 100px;
width: 100px;
margin-bottom: 22px;
padding: 5px;
position: relative;
}
.dz-preview .file-details{height: 40px;width: 200px;}
.dz-preview .dz-filename{
display: block;
height: 100%;
width:100%;
line-height:1.4;
word-wrap:break-word;
overflow: hidden;
}
.dz-preview .dz-size{
position:absolute;
left:3px;
bottom:-28px;
height:28px;
line-height:28px;
overflow: hidden;
}
.dz-preview .img-details img{
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
}
.dz-preview .img-details:hover img{opacity:0.1;}
.dz-preview.dz-error .img-details:hover img{opacity:1;}
.dz-preview .dz-progress{
background: #d7d7d7 none repeat scroll 0 0;
position: absolute;
height:6px;
bottom:0px;
right:0;
left:0;
display:none;
}
.dz-preview.dz-success .dz-progress{display: block;opacity: 0;transition: opacity 0.4s ease-in-out 0s;}
.dz-preview .dz-progress .progress{
border-radius:0;
height:100%;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1) inset;
margin-bottom: 20px;
overflow: hidden;
}
.dz-preview .progress-bar-striped,.dz-preview .progress-striped .progress-bar {
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-size: 14px 14px;
}
.dz-preview .progress-bar.active, .dz-preview .progress.active .progress-bar {
animation: 2s linear 0s normal none infinite running progress-bar-stripes;
}
@-webkit-keyframes progress-bar-stripes {
from {background-position: 40px 0;}to {background-position: 0 0;}
}
@-o-keyframes progress-bar-stripes {
from { background-position: 40px 0;}to {background-position: 0 0;}
}
@keyframes progress-bar-stripes {
from {background-position: 40px 0;}to {background-position: 0 0;}
}
.dz-preview .progress-bar {
background-color: #337ab7;
box-shadow: 0 -1px 0 rgba(0, 0, 0, 0.15) inset;
color: #fff;
float: left;
font-size: 12px;
height: 100%;
line-height: 20px;
text-align: center;
transition: width 0.6s ease 0s;
width: 0;
}
.dz-preview .progress-bar-success {
background-color: #5cb85c;
}
.dz-preview .dz-success-mark, .dz-preview .dz-error-mark{
position: absolute;
top: 5px;
right: 5px;
height: 40px;
width: 40px;
text-align: center;
background-image: url("image/spritemap.png");
background-repeat: no-repeat;
display: black;
opacity: 0;
transition: opacity 0.4s ease-in-out 0s;
}
.dz-preview .dz-success-mark{background-position: -268px -163px;color: #8cc657;}
.dz-preview .dz-error-mark{background-position: -268px -123px;color: #ee162d;}
.dz-preview.dz-success .dz-success-mark,.dz-preview.dz-error .dz-error-mark{filter: none;opacity: 1;}
.dz-preview .dz-error-message{
position: absolute;
left:0px;
top:0px;
width: 100%;
height:100%;
background: rgba(245, 245, 245, 0.8) none repeat scroll 0 0;
color: #800;
padding: 5px 5px;
z-index: 0;
display:none;
}
.dz-preview.dz-error .dz-error-message{z-index:10;transition: opacity 0.3s ease-in-out 0s;}
.dz-preview.dz-error:hover .dz-error-message{display: block;opacity:0.9;}
.dz-preview .del-btn{position:absolute;right:6px;bottom:0px;height:28px;line-height:28px;overflow: hidden;
font-size:12px;color: #800;cursor:pointer;}
页面调用代码就非常精简
//初始化上传组件
$('#content_dom'+index).extWebUploader({
name: 'content',
auto:false,
type:"image",
buttonStyle:'btn-green btn-S',
buttonText:'选择图片',
fileNumLimit:1,
fileSingleSizeLimit:1024*1024*1024*5, //最大5G
duplicate:true,
fileVal:'file',
params:'upType=teachFormFile',
});