公司的项目需要文件上传的功能,之前使用的是SWFUpload这个上传组件,我将其替换成了web uploader。
SWFUpload 最初是Vinterwebb.se 开发的客户端文件上传工具。它联合javascript和flash,在浏览器中提供一个优于传统上传标签 的功能(和良好的用户体验)。
SWFUpload 的主要特性:
文件浏览对话框中可以选择多个文件
AJAX风格的上传,不用重刷新
上传过程中的各种事件.
可以在客户端调节图片大小
它使用的类命名空间兼容各种js库(i.e., jQuery, Prototype, 等.).
支持 Flash 9 and Flash 10 (2.2.0版本后取消对flash 8的支持)
SWFUpload 的设计理念与其他基于flash的上传工具不同。SWFUpload 给开发者尽可能多的UI控制能力. 开发者可以使用 XHTML, CSS, JavaScript 来使它更符合自己网站的样式风格. 它提供一组简单的js事件更新上传状态,开发者可以根据这些事件来在网页中显示文件上传进度
不过不幸的是 Flash Player 10 迫使我们不得不用一个按钮(点击后)才能触发文件选择对话框,但SWFUpload允许开发者用js来修改这个按钮的文字等外观。
从介绍可以看出这个组件是比较老的,主要使用flash来实现上传,在传统上传标签 无法实现多文件上传的时候,他使用flash来实现了。但是新的HTML5中,新加入了multiple属性,只要就可以直接实现多文件上传,此时flash就显得没有必要了。
所以经过一些了解之后,我选择了百度的web Uploader这个上传组件。
WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件。在现代的浏览器里面能充分发挥HTML5的优势,同时又不摒弃主流IE浏览器,沿用原来的FLASH运行时,兼容IE6+,iOS 6+, android 4+。两套运行时,同样的调用方式,可供用户任意选用。
采用大文件分片并发上传,极大的提高了文件上传效率。
该插件使用了HTML5的新特性,以传统的input file 为主,结合flash,使得他在兼容性方面有很大的优势。同时支持移动端上传,非常强大。
官网网址:http://fex.baidu.com/webuploader/
下面是一个简单的示例,我详细做了注释:
//初始化Packing list_uploader对象
var Packing_list_uploader = WebUploader.create({
// swf文件路径
swf: 'js/webuploader/webuploader-0.1.5/Uploader.swf',
// 文件接收服务端。
server: 'UploadOrderFile.action',
// 选择文件的按钮。可选。
// 内部根据当前运行是创建,可能是input元素,也可能是flash.
pick: {
"id":'#packinglist_show_falsh',
"multiple":false //禁止多选。
},
// 文件进入队列后自动开始上传
auto: true,
//分片上传设置
chunked:true, //允许分片
chunkSize:2*1024*1024, //每片大小2M
chunkRetry:4, //分片上传失败之后的重试次数
threads:3, //上传并发数。允许同时最大3个上传进程
//去重
duplicate:true,
//上传文件个数限制
fileNumLimit:20,
//单个文件大小限制 20M
fileSingleSizeLimit:20*1024*1024,
//传入文件格式限制,只能上传doc,docx,pdf格式的文件
accept: {
title: 'Applications',
extensions: 'doc,docx,pdf',
mimeTypes: 'application/pdf, application/msword'
},
//重要参数:跟后台文件组件的对接参数,后台文件组件叫做upload。
fileVal:"upload",
//传入参数。这两个参数会跟文件一起传给后台,用于跟后台对接,确认文件的来源。
formData:{
//这里的两个参数是为了跟后台对接,让后台知道上传的文件存在哪里。
"ttype":"qc_packinglist",
"task":"createqc"
},
});
上边的部分就是上传对象的初始化,我这里是文件上传,跟图片上传略有差异,还有其他很多参数,可以去官网查询API,都写得很清楚。
由于我实在项目中替换原有的上传组件,所以不希望改动界面布局和UI,直接将之前的布局沿用过来,通过id让组件和页面div联系起来。
所以我给初始化之后的对象,增加了一系列属性,属性值设为HTML中相应部分的标签id,通过这些id,在事件中编写相应的函数,可以在不改变界面布局和UI的前提下替换组件。下面是我增加的属性和值。
//给Packing list_uploader对象增加我们自己项目所需要的下列属性:
Packing_list_uploader.bar_id="packing_list_file_panel", //文件上传面板,文件显示,进度条,被他包裹在里边。
Packing_list_uploader.full_progress_bar_id="packing_report_bar", //进度条总长度的div
Packing_list_uploader.percent_bar_id="packing_report_progress_bar", //进度条width变化的div
Packing_list_uploader.related_var="PackingList", //realated_var表示相关的变量,在一个标签中,不在网页中显示,一般用来传递参数。文件上传之后value的值变为has,若必填,检验value的值是否为空。
Packing_list_uploader.file_link_id="packinglist_file_link", //文件上传成功后在id为 order_link的标签中显示文件名,点击可以下载。
Packing_list_uploader.swf_panel_id="packinglist_show_falsh", //放上传flash图标的地方
Packing_list_uploader.del_panel_id="packinglist_show_delete"; //放删除flash图标的地方
//这里多设置了type和task,是因为我没法取得web uploader本身的formDate中的ttype和task的值,不然是可以直接用他们的。
Packing_list_uploader.type="qc_packinglist";
Packing_list_uploader.task="createqc";
最后,得到了需要的对象之后,还需要根据web uploader组件自带的事件来绑定事件函数,得到自己需要的效果。下边的代码是我设置的事件绑定。
//给Packing_list_uploader对象绑定事件和事件函数
//当发生错误的时候触发,判断错误类型,并返回相应的提示。
Packing_list_uploader.on("error",show_error);
// 当有文件添加进来的时候,在文件列表中插入div节点,在网页中显示被插入的文件,包含文件名和等待上传和移除
Packing_list_uploader.on( 'fileQueued',queued );
// 文件上传过程中创建进度条实时显示。上传过程中触发uploadProgress事件,执行函数:
Packing_list_uploader.on( 'uploadProgress',uploading );
//上传成功后显示文件,切换到删除键等。
Packing_list_uploader.on( 'uploadSuccess',upload_ok );
上边的代码中我绑定了一些事件函数,这些函数我写在下边了,也有详细的注释。而且可以支持不同的上传框复用。
//下边所有的函数,都是需要上传的时候公用的函数。不同的uploader对象共用的事件绑定函数 和 这些事件绑定函数中需要调用的函数。
//发生错误时候调用的函数
var show_error=function show_error(type){
if (type=="Q_EXCEED_NUM_LIMIT"){
alert("此处文件数量不能大于1个");
}else if(type=="F_EXCEED_SIZE"){
alert("此处文件大小不能大于20M");
}else if(type=="Q_TYPE_DENIED"){
alert("此处文件类型必须是XXX");
}
};
//文件进入队列时调用的函数
var queued=function queued( file ) {
$("#"+this.bar_id).html(""); //将bar_id对象中的内容清空
var div='this.full_progress_bar_id + '" style="position:relative;width:183px;left:10px;height:8px;display:inline-block;border:1px solid #ccc;list-style:none;margin-top:6px;">this.percent_bar_id +'" style="position:absolute;background-color:#F36861;width:0%;height:8px"> ';
$("#"+this.bar_id).append( div); //加入显示进度条所需的div
};
//文件上传过程中调用的函数
var uploading=function( file, percentage ) {
$("#"+this.percent_bar_id).css( 'width', percentage * 100 + '%');
};
//文件上传成功后调用的函数
var upload_ok=function( file ) { //上传成功时触发uploadSuccess函数,将之前的 上传中 再替换为 已上传。
//调用GetFileList函数,该函数下边
GetFileList(this.type, this.task, this.bar_id, this.related_var,100, this.file_link_id);
//$("#"+this.related_var).next().find("label").remove();//清除上传文件提示
$("#" + this.swf_panel_id).hide(); //上传成功后隐藏上传的flash按钮
$("#" + this.del_panel_id).show(); //上传成功后显示删除文件的flash按钮
//取出对应实例 的参数
var type = this.type;
var task = this.task;
var swf_panel_id = this.swf_panel_id;
var del_panel_id = this.del_panel_id;
var file_link_id = this.file_link_id;
var related_var = this.related_var;
$("#" + this.del_panel_id).click(function(){ //给 删除文件的flash按钮的 click事件绑定 删除上传的文件 的函数
//切换回到上传文件的状态。 该函数在下边。
removeUploadFile(type, task, swf_panel_id, file_link_id, del_panel_id);
$("#" + related_var ).val("");
});
};
//下面是一些上边的调用函数中需要调用的函数:
//取得上传成功的文件,通过该文件制作一个用于点击下载的标签,放入文件上传的地方。
function GetFileList( ty,task, divname,varname, max_len, f_id )
{
var url = 'GetFileList.action';
var params = {"type":ty, "task":task };
$.ajax({
url:url,
type:"POST",
data:params,
dataType:"json",
success:function (data){
var storeObj = document.getElementById(divname);
var t=storeObj.childNodes.length;
for(var i=t-1;i>=0;i--)
{
storeObj.removeChild(storeObj.childNodes[i]);
}
for(var i = 0 ; i var li= document.createElement("li");
var filename = data.list[i].filename;
if( max_len != null && max_len !=undefined && max_len != 'undefined' ){
}
//上传成功后显示文件名字(若太长则显示一部分+省略号...+扩展名),可下载的链接。
li.innerHTML=""+decreaseString(filename,20,true)+" ";
storeObj.appendChild(li);
}
if( data.list.length > 0 )
{
var vv = document.getElementById(varname);
if( vv != null )
vv.value = "has";
}
}
});
}
//根据传入的参数type,task跟后台通信定位文件,删除成功,那么使用上边的switch_delete函数重新切换到上传文件的状态。
function removeUploadFile( type, task, swf_panel_id, swf_filebar_id, del_panel_id ){
var url = 'RemoveUploadFile.action'; //通信删除动作
var params = {"type":type, "task":task };
$.ajax({
url:url,
type:"POST",
data:params,
dataType:"json",
success:function(jdata){
if( jdata.result=="success"){ //判断删除是否成功。
//删除成功后重新切换到上传文件。
switch_delete(swf_panel_id, del_panel_id, swf_filebar_id);
}
},
});
}
//(点击删除文件后)重新切换到上传文件
function switch_delete( flash_id, delete_id, fileplace_id ){
$("#" + flash_id).show(); //显示上传文件的按钮
$("#" + delete_id ).hide(); //隐藏删除文件的按钮
$("#" + fileplace_id ).replaceWith("Upload you document "); //将显示区域的内容替换为上传提示
}