多选文件上传,已经非常多了,选择性多了可能有时候要比较下哪个更合适,结合到项目中使用更方便才是最重要的。很多的多选上传基本上都是调用的swf文件,确实用flash 或flex开发一个多选上传的功能很方便,比如flex里内置的FileReferenceList对象本身就支持文件的多选,有这个的话就方便多了,下面要说的主要也是基于flex开发的一个多选上传功能。
主要实现的功能如下:
一、选择多个文件上传并显示单个文件的上传进度
二、显示所有文件总的上传进度
三、显示所有上传文件的总大小
四、上传前可以删除任意选定一个或多个文件(按住Ctrl或Shift键)
五、ASP.NET页面调用生成的swf文件异步上传到服务器
先看下演示的截图,如下:
大致功能和上面截图一样,下面主要说下ASP.NET里怎么调用,FLEX的里面代码我这里就不详细说明了,FLEX里面的代码不多,文章后面提供下载,用flex3.0或4.0可以打开运行。
其中有一个地方说明一下,就是在多选删除的地方,为了保证随意多选删除的正确性,需要把选定的索引项降序排序,每次从数组最大处删除,避免循环删除时索引超界。
function deleteItem(): void { var selectItems:Array = process_list.selectedItems; var selectIndex:Array = process_list.selectedIndices; selectIndex = selectIndex.sort( 2 ); // 索引按降序排序 var iCount: int = selectItems.length; var sizeMum:Number = 0 ; for ( var i: int = 0 ;i < iCount;i ++ ){ info.splice(selectIndex[i], 1 ); fileRef.fileList.splice(selectIndex[i], 1 ); // 移除的选择项按索引从大到小移除,以便移除过程中索引不超界 } for ( var j:Number = 0 ;j < fileRef.fileList.length;j ++ ){ sizeMum += fileRef.fileList[j].size; } process_list.dataProvider = info; tip_txt.text = " 共 " + fileRef.fileList.length + " 个文件 " + (sizeMum / (1024*1024)).toFixed(4).toString()+"MB"; if (info.length <= 0 ){ delete_btn.enabled = false ; } } 调用其实也比较简单,新建一个aspx页面加载生成的swf文件,这里生成的文件名是upload.swf,利用flex内置的swfobject.js里面的方法加载,如下:
< html xmlns ="http://www.w3.org/1999/xhtml" > < head > < title > 无标题页 </ title > < style type ="text/css" media ="screen" > html, body { height : 100% ; } body { margin : 0 ; padding : 0 ; overflow : auto ; text-align : center ; background-color : #ffffff ; } #flashContent { display : none ; } </ style > < script type ="text/javascript" src ="swfobject.js" ></ script > < script type ="text/javascript" > var swfVersionStr = " 10.0.0 " ; var xiSwfUrlStr = " playerProductInstall.swf " ; var flashvars = {}; flashvars.url = " SaveFile.aspx?Param=ID|100,NAME|测试用户 " ; var params = {}; params.quality = " high " ; params.bgcolor = " #ffffff " ; params.allowscriptaccess = " sameDomain " ; params.allowfullscreen = " true " ; var attributes = {}; attributes.id = " upload " ; attributes.name = " upload " ; attributes.align = " middle " ; swfobject.embedSWF( " upload.swf " , " flashContent " , " 587 " , " 370 " , swfVersionStr, xiSwfUrlStr, flashvars, params, attributes); function uploadCompelete(){ // 完成后的操作,如页面跳转或关闭当前页 document.getElementById( ' btnUpload ' ).disabled = false ; } function submitForm(){ thisMovie( " upload " ).uploadfile(); } function thisMovie(movieName) { if (navigator.appName.indexOf( " Microsoft " ) != - 1 ) { return window[movieName]; } else { return document[movieName]; } } function disabledButton() { document.getElementById( ' btnUpload ' ).disabled = true ; } </ script > </ head > < body > < div id ="flashContent" style ="width:587px; height:380px" > </ div > < br /> < input id ="btnUpload" style ="width: 71px" type ="button" value ="上 传" onclick ="submitForm()" /> </ body > </ html > 如上,页面放置一个按钮,执行upload.swf里面的uploadfile方法,在flex里面其实是回调了uploadHandler方法:
// =================== // 点击上传按钮 // =================== internal function uploadHandler(): void { if (uploadFile_num != 0 ) return ; if (process_list.dataProvider == null || info.length <= 0 ){ Alert.show( " 您还未选择文件! " , " 提示信息 " ); return ; } else { ExternalInterface.call( " disabledButton " ); // 点上传后禁用按钮 } for (var i:Number = 0 ;i < fileRef.fileList.length;i ++ ){ upload_size_total += fileRef.fileList[i].size; } uploadfile(uploadFile_num); add_btn.enabled = false ; // 点上传后禁用浏览按钮 delete_btn.enabled = false ; // 点上传后禁用删除按钮 } SaveFile.aspx页面主要是接收并存储文件,如下:
protected void Page_Load( object sender, EventArgs e){ // string param = Request["Param"]; string path = Server.MapPath( " files/ " ); if ( ! Directory.Exists(path)) { Directory.CreateDirectory(path); } // HttpFileCollection files = Request.Files; // string fileName = string.Empty; // for (int i = 0; i < files.Count; i++) // { // fileName = Path.GetFileName(files[i].FileName).ToLower(); // files[i].SaveAs(path + fileName); // } HttpPostedFile file = Request.Files[ " Filedata " ]; // 文件是一个一个异步提交过来,所以不需要循环文件集合 if (file != null && file.ContentLength > 0 ) { file.SaveAs(path + Request.Form[ " filename " ]); }} 毕竟不是以文件流的形式接收和存储,所以如果是上传大文件的话,可以看到显示页面已经上传完成100%,但是到这个处理存储页面会停顿一会,接收并存储完成后前台页面才会反应过来。
还有一点要提一下,就是如果传递的参数包含中文的话,需要config编码格式为utf-8格式,但有原先的系统可能是gb2312格式的,改成utf-8可能对系统有影响,可以单独建一个webconfig,上传的时候就读单独的config。查了下说flash.system.System.useCodePage=true;设置可以解决中文乱码问题,我试了下还是不好用,最后还是修改的编码格式。
源码下载: (用VS2005及以上或flashbuilder3.0,4.0打开)