SWFUpload
SWF多文件无刷新上传,利用flash完成多文件上传操作。服务器端可以用Struts、Servlet、JSP完成,这里用Struts1.x完成上传
- ??首先看下目录结构
????
SWFUpload这个文件夹是核心文件,里面的文件一个都不能少。
css文件夹是样式文件,所有的样式可以在此文件中修改完成
images是图片
jslib是js库文件,需要的上传的js文件和flash文件
其中handlers.js是上传中一系列的事件,可以在此文件中修改自己的上传所需要的事件。如开始上传、取消、停止上传等
swfupload.queue.js这个文件主要是完成将客户端选择的多一个文件一个个的排成一个队列,然后依次向服务器上传。
swfupload.swf是flash文件,就那个添加或上传的按钮
sample.html是完成后的上传实例
-
首先看看客户端的sample.html中的js和html内容
<!DOCTYPEHTMLPUBLIC"-//W3C//DTD4.01//EN"> <htmlheadtitle>SWFUpload多文件上传示例</metahttp-equiv="content-type"content"text/html;charset=gbk"linkrel"stylesheet"type"text/css"href"css/default.css"script"text/javascript"src"jslib/swfupload.js"></script"jslib/swfupload.queue.js""jslib/fileprogress.js""jslib/handlers.js"charset"utf-8""text/javascript"varswfUpload; window.onload=function(){ settingsflash_url:"jslib/swfupload.swf", upload_url:"../upload.do"post_params:{"param""uploadParams"}file_size_limit"200MB"file_types"*.*"file_post_name:"uploadFile"file_types_description"AllFiles"file_upload_limit: 50, file_queue_limit: 0, custom_settingsprogressTarget"fsUploadProgress"cancelButtonId"btnCancel" debug:true是否显示调试的textarea //Buttonsettings button_image_url:"images/TestImageNoText_65x29.png"button_width:"65"button_height:"29"button_placeholder_id:"spanButtonPlaceHolder"button_text:'<spanclass="theFont">浏览</span>'button_text_style:".theFontfont-size:12;}"button_text_left_padding:12,monospace">button_text_top_padding:3,
Theeventhandlerfunctionsaredefinedinhandlers.js file_queued_handlerfileQueued,monospace">file_queue_error_handler: fileQueueError,monospace">file_dialog_complete_handler: fileDialogComplete,monospace">upload_start_handler: uploadStart,monospace">upload_progress_handler: uploadProgress,monospace">upload_error_handler: uploadError,monospace">upload_success_handler: uploadSuccess,monospace">upload_complete_handler: uploadComplete,monospace">queue_complete_handler: queueComplete ; //自定义属性,是否停止上传 swfUploadnewSWFUpload(settings); swfUpload.stoppedfalse;
functionfileDialogComplete(numberselected,numberqueued)if(swfUpload.getStats().files_queued0)document.getElementById("btnCancel").disabled} }
queueComplete(numberselected,monospace">//alert(numberselected+"-"numberqueued); }
upload()//document.getElementById("btnCancel").disabled=true; swfUpload.startUpload(); }elsealert("请选择要上传的文件!"); } stop()(swfUpload)swfUpload.stopUpload(); } bodydivid"content"h2form"form1"action""method"post"enctype"multipart/form-data"pclass"fieldsetflash""fsUploadProgress"span"legend">上传文件列表spandiv"divMovieContainer"input"filenamelist""hidden"name/> "spanButtonPlaceHolder""button"value"上传"onclick"upload();"style"margin-left:2px;font-size:8pt;height:29px;""停止"stop();""display:none;margin-left:"btnCancel""取消所有"swfUpload.cancelQueue();"disabled"disabled""javaScript:window.close();""bt""关闭form> > |
A.先介绍导入的js文件
>
>
>
这些文件是必须的,且在导入的时候注意你的路径和顺序。还有就文件编码,文件保存的不同编码可以会影响文件显示的乱码问题,charset就是文件保存的编码。
B.然后在其中是script脚本的参数详细讲解
设置flash文件
设置服务器的上传地址
提交到服务器的参数信息,这样就添加了一个param参数,值是uploadParams在服务器端用request.getParameter(“param”)就可以拿到值
上传文件的最大空间
允许上传文件的类型,*.*是所有,*.txt只能上传文本
这个就服务器端要获得的文件的属性,相当于file的name
所有文件夹
上传文件选取的最大队列数
file_queue_limit0,
下面是上传按钮的设置
下面是上传事件和函数:
选择完文件后就触发
file_queued_handler: fileQueued,
上传文件错误时触发
上传文件弹出窗口,窗口关闭触发
开始上传触发
upload_start_handleruploadStart,
上传错误触发
上传成功
完成
队列中上传完成
queue_complete_handler: queueComplete
下面看看html代码:
/>
>
值得介绍的是
>
这个span就会被flsah的浏览多代替,注意这里的id和上面jsbutton_placeholder_id是对应的
/>
这个是上传按钮,点击上传就会执行upload这个js方法
/>
这个是停止上传的,可以取消当前正在上传的文件,运行stop方法
/>
取消所有的队列文件
-
官方的handlers被修改的几个方法
选择文件后显示文件的大小 fileQueued(file)tryvarprogressnewFileProgress(file,monospace">this.customSettings.progressTarget); sizefile.size; unit"B"if(size(1024*10241024))"GB"/=1024); else1021))"MB"; size/= (1024 * 1024); 1024)"KB"size/= 1024; progress.setStatus("<fontcolor='red'>"+size.toFixed(2)"</font>等待上传......"progress.toggleCancel();
catch(ex).debug(ex); } } |
显示当前文件上传进度的百分比
uploadProgress(file,monospace">bytesLoaded,monospace">bytesTotal)percentMath.ceil((bytesLoaded/100);
.customSettings.progressTarget); progress.setProgress(percent); "已上传percent+"%} |
获取服务器端上传后返回的信息
uploadSuccess(file,monospace">serverData)progress.setComplete(); dataeval("("serverData")"(data.success==0||data.success"0")"上传完成{ progress.setError(); progress.setStatus("上传失败data.message); } |
-
下面看看服务器端的上传代码
//上传文件保存路径 publicstaticStringpath"/upload/"//定义可以上传文件的后缀数组默认"*",代表所有 String[]filePostfixs{"*"}; typeImages"gif""jpeg""png""jpg""tif""bmp"typeOthers"html""htm""doc""xls""txt""zip""rar""pdf""cll"}; //上传文件的最大长度 longmaxFileSize2;//2M //一次读取多少字节 intbufferSize8; privatefinalvoidinit()if(Integer.MAX_VALUE8; else<8)1)2L; Long.2L; } /** <b>function:</b>根据传递InputStream,上传文件 @createDateDec19,monospace">20108:53:12PM @paramisInputStream fileName文件名 path保存路径 @return上传状态 @throwsException */ UploadStateupload4Stream(InputStreamis,monospace">fileName,monospace">path)throwsExceptioninit(); stateUploadState.UPLOAD_FAILURE(fileNamenull&&"".equals(fileName))getRandomName(fileName); OutputStreamostrygetDoPath(path); mkDirgetBracketFileName(fileName,monospace">path); newFileOutputStream(pathfileName); read0; byte[]buffer[]; while((readis.read(buffer))!=-1).write(buffer,monospace">read); UPLOAD_SUCCSSScatch(FileNotFoundExceptione) UPLOAD_NOTFOUNDthrowe; (Exceptionfinally(isis.close(); (.flush(); .close(); returnstate; </b>主要针对struts的FormFile进行文件上传 Oct9,monospace">11:22:14fileFormFile 路径 是否上传成功 upload(FormFilefile,monospace">UploadStatefileName= file.getFileName(); InputStream;fileSizefile.getFileSize(); (fileSize<=UPLOAD_ZEROSIZEis= file.getInputStream(); upload4Stream(is,monospace">UPLOAD_OVERSIZE /** </b>struts上传文件,并根据传递的文件类型数组验证上传的文件是否合法 10,monospace">3:53:59PM FormFile 路径 allowTypes文件类型数组 是否上传成功 Exception */ path,monospace">allowTypes){ ; validTypeByName(file.getFileName(),monospace">allowTypes))upload(file,monospace">path); } state; } |
upload4Stream是通过传递InputStream完成上传,这个方法不管是是FormFile、File还是其他的文件对象都可以完成上传。你也可以根据自己的需求进行二次封装完成上传。
上面的上传还用到了其他的验证、命名、路径等辅助方法,详细请看源代码。
验证文件名、类型
/** 根据文件名和类型数组验证文件类型是否合法,flag是否忽略大小写 11:54:54AM 文件名 类型数组 flag是否获得大小写 是否验证通过 booleanvalidTypeByName(StringallowTypes,monospace">flag)suffixgetType(fileName); validfalse(allowTypes.length.equals(allowTypes[0]))truefor(String(flag){//不区分大小写后缀 (suffixsuffix.equalsIgnoreCase(type))break//严格区分大小写 suffix.equals(type))valid; } </b>根据文件名称和类型数组验证文件类型是否合法 10:27:17是否合法 ); 根据后缀和类型数组验证文件类型是否合法,flag是否区分后缀大小写,true严格大小写 12:00:10后缀名 是否区分大小写 validTypeByPostfix(Stringsuffix,monospace"></b>根据文件后缀名和类型数组,验证文件类型是否合法 10:25:32validTypeByPostfix(suffix,monospace"></b>验证当前后缀、文件类型是否是图片类型 typeImages可以设置图片类型 12:17:18验证文件的后缀 validTypeByPostfix4Images(Stringsuffix)</b>验证当前后缀、文件类型是否是非图片类型(常用办公文件类型) typeOthers可以设置文件类型 12:18:18validTypeByPostfix4Others(String</b>验证当前文件名、文件类型是否是图片类型 12:19:18验证文件的名称 validTypeByName4Images(StringfileName)</b>验证当前文件名称、文件类型是否是非图片类型(常用办公文件类型) 12:21:22validTypeByName4Others(String); } |
文件删除操作,对重名的文件可以删除或是替换
</b>传递一个路径和文件名称,删除该文件 10:47:57文件名称 是否删除成功 removeFile(StringisFileExistpath))FileFile((path)fileName); flag =file.delete(); flag; </b>删除文件 10:49:54要删除的文件 removeFile(Filefile)(filefile.exists())flag; } |
获得文件类型、后缀、名称等操作
传入一个文件名,得到这个文件名称的后缀 11:30:46getSuffix(StringindexfileName.lastIndexOf("."); (indexfileName.substring(index);//后缀 suffix; </b>和文件后缀一样,不同的是没有“.” 2:42:43@return getType(StringfileName.substring(index1);传递一个文件名称和一个新名称,组合成一个新的带后缀文件名 当传递的文件名没有后缀,会添加默认的后缀 10:53:06newName新文件名称 nullSuffix为没有后缀的文件所添加的后缀;eg:txt getNewFileName(StringnewName,monospace">nullSuffix)getSuffixnewName +=suffix; newName.concat().concat(nullSuffix); newName; 利用uuid产生一个随机的name 10:45:27带后缀的文件名称 随机生成的getRandomName(StringrandomNameUUID.randomUUID().toString(); getNewFileNamerandomName,monospace">用当前日期、时间和1000以内的随机数组合成的文件名称 11:01:47getNumberName(StringSimpleDateFormatformatSimpleDateFormat("yyMMddhhmmss"randRandom().nextInt(1000); numberNameformat.format(Date())rand; numberName,monospace"></b>判断该文件是否存在 12:00:44目录 是否存在 isFileExist(Stringfile.exists(); </b>返回可用的文件名 1:02:45可用文件名 getBracketFileName(String1); } </b>递归处理文件名称,直到名称不重复(对文件名、目录文件夹都可用) eg:a.txt-->a(1).txt<br/> 文件夹uploadupload(1) 12:56:27文件路径 num累加数字,种子 返回没有重复的名称 bracketName,monospace">num)exist(bracketName,monospace">path); (exist)bracketName =fileName; suffix =fileName.substring(index); bracketName =fileName.substring(0,index); bracketName+=suffix; num++; num); bracketName; </b>处理后的系统文件路径 12:49:31返回处理后的路径 getDoPath(Stringpath.replace("""/"String lastChar= path.substring(path.length() - 1); (!.equals(lastChar))path; 创建指定的path路径目录 11:03:49目录、路径 是否创建成功 mkDir(StringFile(path);(!file.exists())//file.mkdir();创建子目录,如果父目录不存在则不创建 file.mkdirs();(RuntimeExceptione; } |
上面的上传还需要一个上传状态的枚举对象,代码如下:
packagecom.hoo.enums;
文件上传状态 @fileNameUploadState.java 2010-1011下午12:18:14 */ enumUploadState(0,monospace">"上传文件成功!),monospace">(1,monospace">"上传文件失败!UPLOAD_TYPE_ERROR(2,monospace">"上传文件类型错误!(3,monospace">"上传文件过大!(4,monospace">"上传文件为空!(5,monospace">"上传文件路径错误!getState()this.getFlag()UploadState(flag,monospace">state)state; } } |
-
下面看看Struts的ActionForm代码。
com.hoo.form;
importorg.apache.struts.action.ActionForm; org.apache.struts.upload.FormFile;
@SuppressWarnings"serial") classUploadFileFormextendsActionFormFormFileuploadFilegetUploadFile()}
setUploadFile(FormFileuploadFile)uploadFile; paramgetParam()setParam(Stringparam)param; } |
uploadFile这个属性是和客户端js中的file_post_name:"uploadFile"属性对应,这个一定要注意,param属性是和客户端的post_params:{"param":"uploadParams"}
中的param对应,如果你还有其他参数都会在这里列举。如果你是上传的时候,文件名出现乱码,那么你最好在这里把文件名用encodeURI转码2次。通过post_params传递到服务器端,然后服务器端用URLDecoder转码即可。
-
服务器端上传代码,很简单直接调用UploadFormFileUtils工具类完成上传
com.hoo.action;
com.hoo.util.UploadFormFileUtils.com.hoo.util.UploadFormFileUtils.javax.servlet.http.HttpServletRequest; javax.servlet.http.HttpServletResponse; org.apache.struts.action.Action; org.apache.struts.action.ActionForward; org.apache.struts.action.ActionMapping; org.apache.struts.upload.FormFile; com.hoo.enums.UploadState; com.hoo.form.UploadFileFormcom.hoo.util.UploadFormFileUtils;
struts多文件上传 5:14:43@fileUploadAction.java @packagecom.hoo.action @projectStrutsUpload @version1.0 UploadActionAction{
ActionForwardexecute(ActionMappingmapping,monospace">form,monospace">HttpServletRequestrequest,monospace">HttpServletResponseresponse)uForm)form;request.getSession().getServletContext().getRealPath(UploadFormFileUtils.20L; FormFilefile = uForm.getUploadFile(); file.getFileName(),monospace">System.out.println(uForm.getParam()); response.getWriter().print("{success:state.getFlag()",message:'"state.getState()"'}"} |
注意:这里上传就是一个方法,很普通的方法。也就是上传一个文件,其实SWFupload的上传是利用queue队列,将队列中的文件依次通过flash向服务器端完成上传。而并不是一次上传或是批量上传。
);
和客户端的handlers.js函数中的uploadSuccess中的serverData中的内容对应的
);
{
progress.setError();
data.message);
}
这里是将服务器端传递过来的json字符用eval转换成js对象,data就是一个js对象
data.success这里的success就是服务器端字符串中success的值,同样message也是服务器端字符串后面的值。
Strtus-config.xml配置
struts-configdata-sourcesform-beansform-bean"uploadForm""com.hoo.form.UploadFileForm"global-exceptionsglobal-forwardsaction-mappingsaction"/upload""com.hoo.action.UploadAction"scope"request"message-resourcesparameter"struts.ApplicationResources"/> > |
支持struts1.x的SWFUpload多文件无刷新上传就到此结束。其中对主要的几个文件和js文件中要注意到的地方都指出过。且提供源代码参考,这里提供方法的基本上够用,能完成上传、提示、验证等。
下次有时间会提供ExtJS+SWFUpload+Struts2.x的多文件上传,这个界面更加友好、人性化、功能将更加丰富。
我的博客:http://hoojo.cnblogs.com/
http://blog.csdn.net/IBM_hoojo