一般的WEB方式文件上传只能一个一个的进行上传,在某些应用上就显得很不人性化,客户们都希望能够1次选择很多文件,然后让系统把选择的文件全部上传。

这里,就将针对这个问题提出一个比较完美的解决方案,利用的技术主要有2个:Flash 和 smartupload。Flash 能够让客户一次选择多个文件,而smartupload负责将选择的文件上传到服务器上。

有些朋友看到这里,就知道了,其实就是swfupload方法,具体信息可以访问swfupload官方网站:http://www.swfupload.org/
让我们先来看看客户端的界面效果图。(多选文件,批量上传,上传进度显示)

SWFUpload上传_javascript

要做到图中的效果,其实很方便,看完下面的描述,相信大家都可以实现上图中的效果了。
说明:swfupload2中通过一个png图片与flash插件进行关联,可以修改images下的png图片来(如上图中的[选择文件]图片)自定义显示自己想要的图片样子(不要修改图片名字和格式)。

如果你用的不是java环境,不要紧,只要稍作修改,同样可以使用在其他的环境中。

第1步,要进行下面的过程,必须先准备好Flash插件和smartupload。
Flash插件:相信大家的浏览器早已经安装过了,请检查版本,尽量使用最新的的flash插件。

smartupload:大家可以去看看我的另一篇文章 [上传下载组件SmartUpload使用方法] http://stephen830.javaeye.com/blog/255010 里面详细讲述了使用方法,并且提供了具体java类的下载。请先熟悉smartupload,然后再开始下面的步骤。

第2步,前台部分准备客户操作的WEB界面 ,如下[UploadFileExample.jsp、UploadFileExampleSubmit.jsp]


(关于参数 upload_url: "<%=uploadUrl.toString()%>",
要注意提交文件路径,最好用http://.../UploadFileExample.jsp格式的完整路径,即像我例子中写的那样)

 

UploadFileExample.jsp

Java代码  SWFUpload上传_javascript_02SWFUpload上传_sed_03
  1. <%@ page contentType="text/html;charset=UTF-8"%>  
  2. <%  
  3.     double perMaxSize = 1.5;//单个文件允许的max大小  
  4.     String sizeUnit = "MB";//perMaxSize数据对应的单位  
  5.     String ext = "*.jpg;*.jpeg;*.gif";//允许上传的文件类型  
  6.     //文件上传提交的目标页面  
  7.     StringBuffer uploadUrl = new StringBuffer("http://");  
  8.     uploadUrl.append(request.getHeader("Host"));  
  9.     uploadUrl.append(request.getContextPath());  
  10.     uploadUrl.append("/admin/swfuploadexample/UploadFileExampleSubmit.jsp");  
  11. %>  
  12. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
  13. <html>  
  14. <head>  
  15. <title>批量相片上传</title>  
  16. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
  17. <link href="css/default.css" rel="stylesheet" type="text/css" />  
  18. <script type="text/javascript" src="js/swfupload.js"></script>  
  19. <script type="text/javascript" src="js/swfupload.swfobject.js"></script>  
  20. <script type="text/javascript" src="js/swfupload.queue.js"></script>  
  21. <script type="text/javascript" src="js/fileprogress.js"></script>  
  22. <script type="text/javascript" src="js/handlers.js"></script>  
  23.   
  24. <script type="text/javascript">  
  25. var swfu;  
  26.   
  27. SWFUpload.onload = function () {  
  28.     var settings = {  
  29.         flash_url : "js/swfupload.swf",  
  30.         upload_url: "<%=uploadUrl.toString()%>",  
  31.         post_params: {  
  32.             "user_id" : "stephen830",  
  33.             "pass_id" : "123456"  
  34.         },  
  35.         file_size_limit : "<%=perMaxSize%> <%=sizeUnit%>",  
  36.         file_types : "<%=ext%>",  
  37.         file_types_description : "<%=ext%>",  
  38.         file_upload_limit : 100,  
  39.         file_queue_limit : 0,  
  40.         custom_settings : {  
  41.             progressTarget : "fsUploadProgress",  
  42.             cancelButtonId : "btnCancel",  
  43.             uploadButtonId : "btnUpload",  
  44.             myFileListTarget : "idFileList"  
  45.         },  
  46.         debug: false,  
  47.         auto_upload:false,  
  48.   
  49.         // Button Settings  
  50.         button_image_url : "images/XPButtonUploadText_61x22.png",   // Relative to the SWF file  
  51.         button_placeholder_id : "spanButtonPlaceholder",  
  52.         button_width: 61,  
  53.         button_height: 22,  
  54.   
  55.         // The event handler functions are defined in handlers.js  
  56.         swfupload_loaded_handler : swfUploadLoaded,  
  57.         file_queued_handler : fileQueued,  
  58.         file_queue_error_handler : fileQueueError,  
  59.         file_dialog_complete_handler : fileDialogComplete,  
  60.         upload_start_handler : uploadStart,  
  61.         upload_progress_handler : uploadProgress,  
  62.         upload_error_handler : uploadError,  
  63.         upload_success_handler : uploadSuccess,  
  64.         upload_complete_handler : uploadComplete,  
  65.         queue_complete_handler : queueComplete, // Queue plugin event  
  66.           
  67.         // SWFObject settings  
  68.         minimum_flash_version : "9.0.28",  
  69.         swfupload_pre_load_handler : swfUploadPreLoad,  
  70.         swfupload_load_failed_handler : swfUploadLoadFailed  
  71.     };  
  72.   
  73.     swfu = new SWFUpload(settings);  
  74. }  
  75.   
  76. </script>  
  77. </head>  
  78. <body bgcolor="#FCFCFC" topmargin="0px" leftmargin="10px" rightmargin="10px" scroll="yes">  
  79. <table width="100%" cellspacing="4" cellpadding="4" border="0" bgcolor="#FCFCFC">  
  80.     <tr>   
  81.     <td class="DH1">  
  82.     <table width="100%" cellspacing="4" cellpadding="4" border="0" bgcolor="#FCFCFC">  
  83.     <tr>  
  84.     <td class="DH2">  
  85.     <STRONG>批量上传相片 (支持的相片类型:<%=ext%>;单个相片最大不能超过:<%=perMaxSize%> <%=sizeUnit%>)</STRONG>   
  86.     </td><td class="DH2" align="right"></td>  
  87.     </tr>  
  88.     </table>  
  89. <div id="content">  
  90.     <form id="form1" action="UploadFileExampleSubmit.jsp" method="post" enctype="multipart/form-data">  
  91.         <table width="90%" cellspacing="0" cellpadding="0" border="0"><tr><td>  
  92.         <span id="spanButtonPlaceholder"></span>  
  93.         <input id="btnUpload" type="button" value="上传相片" class="btn" />  
  94.         <input id="btnCancel" type="button" value="取消全部上传" disabled="disabled" class="btn" /></td>  
  95.         </tr></table>  
  96.         <table id="idFileList" class="uploadFileList"><tr class="uploadTitle"><td><B> 文件名</B></td><td><B>文件大小</B>< /td><td width=100px><B>状态</B></td>< td width=35px>&nbsp;</td></tr></table>  
  97.         等待上传 <span id="idFileListCount">0</span> 个 ,成功上传 <span id="idFileListSuccessUploadCount">0</span> 个  
  98.         <div id="divSWFUploadUI" style="visibility: hidden;"></div>  
  99.         <noscript style="display: block; margin: 10px 25px; padding: 10px 15px;">  
  100.             很抱歉,相片上传界面无法载入,请将浏览器设置成支持JavaScript。  
  101.         </noscript>  
  102.         <div id="divLoadingContent" class="content" style="background-color: #FFFF66; border-top: solid 4px #FF9966; border-bottom: solid 4px #FF9966; margin: 10px 25px; padding: 10px 15px; display: none;">  
  103.             相片上传界面正在载入,请稍后...  
  104.         </div>  
  105.         <div id="divLongLoading" class="content" style="background-color: #FFFF66; border-top: solid 4px #FF9966; border-bottom: solid 4px #FF9966; margin: 10px 25px; padding: 10px 15px; display: none;">  
  106.             相片上传界面载入失败,请确保浏览器已经开启对JavaScript的支持,并且已经安装可以工作的Flash插件版本。  
  107.         </div>  
  108.         <div id="divAlternateContent" class="content" style="background-color: #FFFF66; border-top: solid 4px #FF9966; border-bottom: solid 4px #FF9966; margin: 10px 25px; padding: 10px 15px; display: none;">  
  109.             很抱歉,相片上传界面无法载入,请安装或者升级您的Flash插件。  
  110.             请访问: <a href="http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash" target="_blank">Adobe网站</a> 获取最新的Flash插件。  
  111.         </div>  
  112.     </form>  
  113. </div>  
  114. </td></tr></table>  
  115. </body>  
  116. </html>  
<%@ page contentType="text/html;charset=UTF-8"%>
<%
    double perMaxSize = 1.5;//单个文件允许的max大小
    String sizeUnit = "MB";//perMaxSize数据对应的单位
    String ext = "*.jpg;*.jpeg;*.gif";//允许上传的文件类型
    //文件上传提交的目标页面
	StringBuffer uploadUrl = new StringBuffer("http://");
	uploadUrl.append(request.getHeader("Host"));
	uploadUrl.append(request.getContextPath());
	uploadUrl.append("/admin/swfuploadexample/UploadFileExampleSubmit.jsp");
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>批量相片上传</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="css/default.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="js/swfupload.js"></script>
<script type="text/javascript" src="js/swfupload.swfobject.js"></script>
<script type="text/javascript" src="js/swfupload.queue.js"></script>
<script type="text/javascript" src="js/fileprogress.js"></script>
<script type="text/javascript" src="js/handlers.js"></script>

<script type="text/javascript">
var swfu;

SWFUpload.onload = function () {
	var settings = {
		flash_url : "js/swfupload.swf",
		upload_url: "<%=uploadUrl.toString()%>",
		post_params: {
			"user_id" : "stephen830",
			"pass_id" : "123456"
		},
		file_size_limit : "<%=perMaxSize%> <%=sizeUnit%>",
		file_types : "<%=ext%>",
		file_types_description : "<%=ext%>",
		file_upload_limit : 100,
		file_queue_limit : 0,
		custom_settings : {
			progressTarget : "fsUploadProgress",
			cancelButtonId : "btnCancel",
			uploadButtonId : "btnUpload",
			myFileListTarget : "idFileList"
		},
		debug: false,
		auto_upload:false,

		// Button Settings
		button_image_url : "images/XPButtonUploadText_61x22.png",	// Relative to the SWF file
		button_placeholder_id : "spanButtonPlaceholder",
		button_width: 61,
		button_height: 22,

		// The event handler functions are defined in handlers.js
		swfupload_loaded_handler : swfUploadLoaded,
		file_queued_handler : fileQueued,
		file_queue_error_handler : fileQueueError,
		file_dialog_complete_handler : fileDialogComplete,
		upload_start_handler : uploadStart,
		upload_progress_handler : uploadProgress,
		upload_error_handler : uploadError,
		upload_success_handler : uploadSuccess,
		upload_complete_handler : uploadComplete,
		queue_complete_handler : queueComplete,	// Queue plugin event
		
		// SWFObject settings
		minimum_flash_version : "9.0.28",
		swfupload_pre_load_handler : swfUploadPreLoad,
		swfupload_load_failed_handler : swfUploadLoadFailed
	};

	swfu = new SWFUpload(settings);
}

</script>
</head>
<body bgcolor="#FCFCFC" topmargin="0px" leftmargin="10px" rightmargin="10px" scroll="yes">
<table width="100%" cellspacing="4" cellpadding="4" border="0" bgcolor="#FCFCFC">
	<tr> 
	<td class="DH1">
	<table width="100%" cellspacing="4" cellpadding="4" border="0" bgcolor="#FCFCFC">
	<tr>
	<td class="DH2">
	<STRONG>批量上传相片 (支持的相片类型:<%=ext%>;单个相片最大不能超过:<%=perMaxSize%> <%=sizeUnit%>)</STRONG> 
	</td><td class="DH2" align="right"></td>
	</tr>
	</table>
<div id="content">
	<form id="form1" action="UploadFileExampleSubmit.jsp" method="post" enctype="multipart/form-data">
		<table width="90%" cellspacing="0" cellpadding="0" border="0"><tr><td>
		<span id="spanButtonPlaceholder"></span>
		<input id="btnUpload" type="button" value="上传相片" class="btn" />
		<input id="btnCancel" type="button" value="取消全部上传" disabled="disabled" class="btn" /></td>
		</tr></table>
		<table id="idFileList" class="uploadFileList"><tr class="uploadTitle"><td><B>文件名</B></td><td><B>文件大小</B></td><td width=100px><B>状态</B></td><td width=35px>&nbsp;</td></tr></table>
		等待上传 <span id="idFileListCount">0</span> 个 ,成功上传 <span id="idFileListSuccessUploadCount">0</span> 个
		<div id="divSWFUploadUI" style="visibility: hidden;"></div>
		<noscript style="display: block; margin: 10px 25px; padding: 10px 15px;">
			很抱歉,相片上传界面无法载入,请将浏览器设置成支持JavaScript。
		</noscript>
		<div id="divLoadingContent" class="content" style="background-color: #FFFF66; border-top: solid 4px #FF9966; border-bottom: solid 4px #FF9966; margin: 10px 25px; padding: 10px 15px; display: none;">
			相片上传界面正在载入,请稍后...
		</div>
		<div id="divLongLoading" class="content" style="background-color: #FFFF66; border-top: solid 4px #FF9966; border-bottom: solid 4px #FF9966; margin: 10px 25px; padding: 10px 15px; display: none;">
			相片上传界面载入失败,请确保浏览器已经开启对JavaScript的支持,并且已经安装可以工作的Flash插件版本。
		</div>
		<div id="divAlternateContent" class="content" style="background-color: #FFFF66; border-top: solid 4px #FF9966; border-bottom: solid 4px #FF9966; margin: 10px 25px; padding: 10px 15px; display: none;">
			很抱歉,相片上传界面无法载入,请安装或者升级您的Flash插件。
			请访问: <a href="http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash" target="_blank">Adobe网站</a> 获取最新的Flash插件。
		</div>
	</form>
</div>
</td></tr></table>
</body>
</html>

 UploadFileExample.jsp对应的处理页面 --> UploadFileExampleSubmit.jsp

(1)请确保已经看完我的另一篇文章(上传下载组件SmartUpload使用方法 http://stephen830.javaeye.com/admin/blogs/255010 ),先搞好这个才能开始下面的操作
(2)写一个对应上传方法类,com.soft4j.bo.PhotoMgr.java,其中的方法就是文章下面提到的public static String fileUpload(SmartUpload su,PageContext pageContext) throws Exception {...}

这2点弄好了,ok,可以继续。(如果没有准备java文件,下面的UploadFileExampleSubmit.jsp会报错)

注意在(UploadFileExampleSubmit.jsp)中:上传成功后必须返回“successed”,失败的话则返回失败的原因。

Java代码  SWFUpload上传_javascript_02SWFUpload上传_sed_03
  1. <%@ page contentType="text/html;charset=UTF-8"%><%@ page import="com.soft4j.httpupload4j.SmartUpload"%><%@ page import="com.soft4j.bo.PhotoMgr"%><%  
  2.     String pageErrorInfo = null;  
  3.     SmartUpload su = null;  
  4.     try{  
  5.         su = new SmartUpload();  
  6.         su.initialize(pageContext);  
  7.         su.upload();  
  8.         pageErrorInfo = PhotoMgr.fileUpload(su,pageContext);  
  9.         if(pageErrorInfo==null){  
  10.             out.print("successed");  
  11.         }  
  12.     }catch(Exception e){  
  13.         pageErrorInfo = e.getMessage();  
  14.     }finally{  
  15.         su = null;  
  16.         if(pageErrorInfo!=null){  
  17.             out.print(pageErrorInfo);  
  18.         }  
  19.     }  
  20. %>  
<%@ page contentType="text/html;charset=UTF-8"%><%@ page import="com.soft4j.httpupload4j.SmartUpload"%><%@ page import="com.soft4j.bo.PhotoMgr"%><%
	String pageErrorInfo = null;
	SmartUpload su = null;
	try{
		su = new SmartUpload();
		su.initialize(pageContext);
		su.upload();
		pageErrorInfo = PhotoMgr.fileUpload(su,pageContext);
		if(pageErrorInfo==null){
			out.print("successed");
		}
	}catch(Exception e){
		pageErrorInfo = e.getMessage();
	}finally{
		su = null;
		if(pageErrorInfo!=null){
			out.print(pageErrorInfo);
		}
	}
%>

 第3步 准备后台的文件上传功能。 也就是上面文件[UploadFileExampleSubmit.jsp]中用到的[PhotoMgr.fileUpload(su,pageContext)]方法。

Java代码  SWFUpload上传_javascript_02SWFUpload上传_sed_03
  1. /**  
  2.      * 文件上传方法.  
  3.      * @param su  
  4.      * @param pageContext  
  5.      * @return  
  6.      * @throws Exception  
  7.      */  
  8.     public static String fileUpload(SmartUpload su,PageContext pageContext) throws Exception {  
  9.         com.soft4j.httpupload4j.File suFile = null;  
  10.         int fileCount = 0;  
  11.         try {  
  12.             //获取传递过来的参数  
  13.             String userId = su.getRequest().getParameter("user_id");  
  14.             String passId = su.getRequest().getParameter("pass_id");  
  15.   
  16.             String fileExt = "";  
  17.             int fileSize = 0;  
  18.             String AllowedExtensions = ",jpg,jpeg,gif,";//允许上传的文件类型  
  19.             double maxFileSize = 1.5*1024;//单文件最大大小,单位KB  
  20.             //校验文件类型和大小  
  21.             for (int i=0; i<su.getFiles().getCount();i++) {  
  22.                 suFile = su.getFiles().getFile(i);  
  23.                 if (suFile.isMissing())  
  24.                     continue;  
  25.                 //校验文件大小  
  26.                 fileSize = suFile.getSize()/1024;//字节转换成KB  
  27.                 if(fileSize==0) fileSize=1;  
  28.                 if(maxFileSize<fileSize) throw new Exception("单个上传相片的容量不能超过["+maxFileSize+"KB]");  
  29.       
  30.                 //校验文件类型  
  31.                 if (suFile.getFileExt() == null  
  32.                         || "".equals(suFile.getFileExt())) {  
  33.                     fileExt = ",,";  
  34.                 } else {  
  35.                     fileExt = "," + suFile.getFileExt().toLowerCase() + ",";  
  36.                 }  
  37.                 if (!"".equals(AllowedExtensions)  
  38.                         && AllowedExtensions.indexOf(fileExt) == -1) {  
  39.                     throw new Exception("您上传的文件[" + suFile.getFileName()  
  40.                             + "]的类型为系统禁止上传的文件类型,不能上传!");  
  41.                 }  
  42.                 fileCount++;  
  43.             }  
  44.             if (fileCount==0) throw new Exception("请选择上传的文件");  
  45.             //准备保存文件  
  46.             String filePath="D://tomcat//webapps//test//photo//";//这里填写项目中存放上传文件的物理路径  
  47.             for (int i=0; i<su.getFiles().getCount();i++) {  
  48.                 suFile = su.getFiles().getFile(i);  
  49.                 suFile.saveAs(filePath+suFile.getFileName(),SmartUpload.SAVE_PHYSICAL);//保存文件  
  50.             }  
  51.             //成功返回null  
  52.             return null;  
  53.         } finally {  
  54.             //  
  55.         }  
  56.     }  
/**
	 * 文件上传方法.
	 * @param su
	 * @param pageContext
	 * @return
	 * @throws Exception
	 */
	public static String fileUpload(SmartUpload su,PageContext pageContext) throws Exception {
	    com.soft4j.httpupload4j.File suFile = null;
	    int fileCount = 0;
	    try {
	    	//获取传递过来的参数
	    	String userId = su.getRequest().getParameter("user_id");
	    	String passId = su.getRequest().getParameter("pass_id");

	        String fileExt = "";
	        int fileSize = 0;
	        String AllowedExtensions = ",jpg,jpeg,gif,";//允许上传的文件类型
	        double maxFileSize = 1.5*1024;//单文件最大大小,单位KB
	        //校验文件类型和大小
	        for (int i=0; i<su.getFiles().getCount();i++) {
	            suFile = su.getFiles().getFile(i);
	            if (suFile.isMissing())
	                continue;
	            //校验文件大小
	            fileSize = suFile.getSize()/1024;//字节转换成KB
	            if(fileSize==0) fileSize=1;
	            if(maxFileSize<fileSize) throw new Exception("单个上传相片的容量不能超过["+maxFileSize+"KB]");
	
	            //校验文件类型
	            if (suFile.getFileExt() == null
	                    || "".equals(suFile.getFileExt())) {
	                fileExt = ",,";
	            } else {
	                fileExt = "," + suFile.getFileExt().toLowerCase() + ",";
	            }
	            if (!"".equals(AllowedExtensions)
	                    && AllowedExtensions.indexOf(fileExt) == -1) {
	                throw new Exception("您上传的文件[" + suFile.getFileName()
	                        + "]的类型为系统禁止上传的文件类型,不能上传!");
	            }
	            fileCount++;
	        }
	        if (fileCount==0) throw new Exception("请选择上传的文件");
	        //准备保存文件
	        String filePath="D://tomcat//webapps//test//photo//";//这里填写项目中存放上传文件的物理路径
	        for (int i=0; i<su.getFiles().getCount();i++) {
	            suFile = su.getFiles().getFile(i);
	            suFile.saveAs(filePath+suFile.getFileName(),SmartUpload.SAVE_PHYSICAL);//保存文件
	        }
	        //成功返回null
	        return null;
	    } finally {
	    	//
	    }
	}

 备注:关于jsp页面和java方法我不做过多的说明了,应该已经比较清楚了。

本文自发布后,受到了很多朋友的关注,也为不少的朋友提供了帮助,我很高兴。
下面将朋友们遇到的一些问题作汇总后需要注意的一些地方列了出来:

<1> 功能实现需要flash插件支持。
flash版本为 flash 9.0.124 或者 flash 10.0.12.36 版本(这是最新的flash10插件). 如果不是的话,可以去flash官网 http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash 进行在线安装。


<2> UploadFileExample.jsp 中的 upload_url参数设置。
参数需要使用 http://....../UploadFileExampleSubmit.jsp 这样的完整路径.

<3> 关于获取参数 post_params中的参数值。
post_params: {"user_id" : "stephen830","pass_id" : "123456"} 中的参数,不能使用普通的request.getParameter("")方法来获取,
而必须用你的上传方法对应的特定方法来获取,比如,我这里用smartupload,则获取方法就是String userId = su.getRequest().getParameter("user_id");

<4> 上传后不管成功还是失败,都需要有返回值。
这个返回值将传递到对应js中。返回值在UploadFileExampleSubmit.jsp中设置,成功则 out.print("successed"); 失败则 out.print(pageErrorInfo);//pageErrorInfo为错误信息。

该返回值将传递给js目录下的handlers.js文件,具体的方法是 function uploadSuccess(file, serverData) {...} 。

有些朋友的上传成功后out.print("successed"); 发现js收到的"successed"前面会有隐藏字符,遇到这种情况可以更改function uploadSuccess(file, serverData) {...} 中的
var isSuccess = (serverData.indexOf("successed")==0?true:false);
改为
var isSuccess = (serverData.indexOf("successed")>-1?true:false);
就可以了。

附录:swfupload 文件批量上传压缩包 swfupload.zip(支持最新的flash10插件) (附件中没有java类,请自己准备1个java类,将上面的方法复制进去)
为方便了解和调试功能,在附件中增加了一个完整的工程Example,附件名(PROJECT_swfupload.zip),大家可以直接使用来测试功能。