uploadify在struts2下的使用

1、首先准备uploadify上传插件包,拷贝到项目目录下



2、注意其中的特殊文件:uploadify-init.js文件,是包含了封装后的特殊函数:

/**
 * uploadify上传插件相关JS
 */
$.extend( {

	/**
	 * uploadify上传插件初始化设置
	 * params:
	 * 
	 */
	initUploadify : function(params) {
		var opts = {
				//'buttonImage' : '',				// 选择文件按钮图片
				'buttonClass' : 'but but_blue',		// 选择文件按钮样式
				'debug': false,						// 是否开启调试模式
				'auto': true,						// 是否自动上传
				'multi': true,						// 是否允许多个上传
				'removeCompleted': true,			// 上传完毕上传列表是否消失
				'removeTimeout': 0,					// 上传完毕到列表消失的间隔时间
				'fileObjName': 'uploadFile',		// 上传文件数据的名字(服务器端获取文件时使用的名字)
				'queueID': false,				// 装载进度条的标签ID
				'progressData': 'percentage',		// 进度条效果percentage或speed 
				'buttonText': '上传',				// 上传按钮文本内容
				'formData' : {},				// 表单数据(json格式)
				'method': 'post',					// 提交方法(post或get)
				'fileSizeLimit': '2MB',				// 上传文件大小设置 单位可以是B、KB、MB、GB
				'fileTypeDesc' : '*.gif; *.jpg; *.png',		// 选择文件框类型处提示文本
				'fileTypeExts' : '*.gif; *.jpg; *.png',		// 上传时支持的文件类型
				'swf': 'js/uploadify/uploadify.swf',// swf文件位置(必设参数,插件自带文件,不可替换)
				'width': 120,						// 上传按钮宽度
				'height': 30,						// 上传按钮高度
				'successTimeout': 999999,			// 上传超时时间,若达到时间服务器没有响应,则当作成功(很扯淡的设置,默认为30秒)
				'uploader': '',			// 服务器处理上传的Action 
				'queueSizeLimit': 10,				// 允许一次上传的文件数
				'uploadLimit': 999999,				// 允许的总上传文件次数(刷新页面后重置)
				//'overrideEvents' : [],			// 设置不执行的默认事件				
				// 选中文件时事件
				'onSelect': function (event, queueID, fileObj) {
					
				},				
				// 上传文件出错事件
				'onUploadError': function (file,errorCode,errorMsg,errorString,swfuploadifyQueue) {					
					alert(errorMsg);
				},				
				// 上传完成时事件
				'onUploadComplete': function (file) {
					
				},				
				// 上传时发生错误事件
				'onUploadError': function (file, errorCode, errorMsg) {
					var msg = "服务器故障。";
					switch(errorCode) {
						case -100:
							msg = "上传的文件数量已经超出系统限制的"+$('#file_upload').uploadify('settings','queueSizeLimit') + "个文件。";
		                    break;
		                case -110:
		                    msg = "文件 ["+file.name+"] 大小超出系统限制的" + $('#file_upload').uploadify('settings','fileSizeLimit') + "大小。";
		                    break;
		                case -120:
		                	msg = "文件 ["+file.name+"] 大小异常。";
		                    break;
		                case -130:
		                	msg = "文件 ["+file.name+"] 类型不正确。";
		                    break;
		                case -280:
		                	return;
					}
					alert(msg);
				},				
				// 检测Flash失败调用
		        'onFallback': function(){
					var fallBackMsg = '您未安装Flash控件,无法上传图片!请安装FLASH控件后再试。';
					alert(fallBackMsg);
		        },		        
		        // 成功上传到服务器,服务器返回相应信息(服务器回写的数据存放于data中)
		        'onUploadSuccess': function(file, data, response){
		        	
		        },
		        inputFile:"#file_upload"
			};
		if (typeof params !== "undefined")
			$.extend(opts,params);
		
		if (typeof opts.uploader === "undefined" || opts.uploader === ""){
			alert("必须指定上传的地址");
			return;
		}
		if (typeof opts.inputFile === "undefined" || opts.inputFile === ""){
			alert("没有指定上传表单元素");
			return;
		}
		$(opts.inputFile).uploadify(opts);
	}
});


3、客户端调用实例

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="http://localhost:8080/snjob/">    
    <title>上传示范</title>
   	
<link rel="stylesheet" href="js/uploadify/uploadify.css" type="text/css" />
<script type="text/javascript" src="js/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="js/uploadify/jquery.uploadify.min.js"></script>
<script type="text/javascript" src="js/uploadify/uploadify-init.js"></script>
   	<style type="text/css">
   		body{
   			font-size:12px;
   		}
   		.uploadform{
   			background-color: gray;
   			border:1px solid;
   		}
   		table{
   			80%;
   			border- 1px;  			
   		}
   	</style>
   	<script type="text/javascript">
   		$(function(){
   			
   		   	$.initUploadify({
				inpufFile:"#file_upload",
				uploader:'http://localhost:8080/snjob/corpasyn/UploadAction!uploadMethod1.action',
				formData:{param1 : "jiang"},
				onUploadSuccess:function(file, ptl, response){
					eval("var ptl = "+ptl);
					var d = new Date();
					
		        	if (ptl.status==="Success"){
						var tr = "<tr>";
						tr+="<td>"+file.name+"</td>";
						tr+="<td>"+(file.size/1024)+"K</td>";
						tr+="<td>"+d+"</td>";
						tr+="<td><a href='2/"+ptl.data+"'>下载</a></td>";
						tr+="</tr>";
						$("table tbody").append(tr);
				    } else {
					    alert(ptl.msg);
				    }
		        }
   	   		 });
   	   	});
   	</script>
  </head>  
  <body>
  	<h3>上传文件示范</h3>
  	<div class="uploadform">
  		<input id="file_upload" type="file" name="file_upload" />
  	</div>
  	<h5>文件列表</h5>
  	<div>
  		<table id="upfiles" border="1">
  			<tbody>
  				<tr>
	  				<th>文件名</th>
	  				<th>文件大小</th>
	  				<th>上传时间</th>
	  				<th>操作</th>
  				</tr>
  			</tbody>
  		</table>
  	</div>
  	
  	<a href="demo/corp_feedback.jsp"><h3>Ajax异步加载示范和Ajax分页示范</h3></a>
  </body>
</html>


4、运行效果:



5、看一下最关心的服务器代码是如何编写的

服务器采用Struts2,具体Action的设计如下:


我们要直接使用的是UploadDemoAction。

BaseAction源码:

package org.job.web.action;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.InvalidParameterException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;


import org.apache.struts2.ServletActionContext;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.json.annotations.JSON;
import org.apache.struts2.util.ServletContextAware;
import org.job.biz.ServiceTemplate;



import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;



/**
 * Action类的基类,实现了ServletRequestAware接口、ServletResponseAware接口、ServletContextAware接口用于注入Servlet对象,因此与Servlet API有耦合
 * 也可以采用ServletActionContext.getXxx()方法实现访问Servlet API更加优雅
 * @author 江橦
 *
 */

public abstract  class BaseAction extends ActionSupport implements ServletRequestAware,ServletResponseAware,ServletContextAware,IAction {	
	
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 7897085684034354314L;
	
	
	

	/**
	 * 添加属性到请求上下文
	 * @param key
	 * @param value
	 */
	protected void addAttr(String key,Object value,VScope...scopes){
		VScope scp = scopes==null||scopes.length==0?VScope.REQ:scopes[0];
		switch (scp) {
		case PAGE:
			((java.util.Map<String,Object>)ActionContext.getContext().get("page")).put(key, value);
			break;
		case REQ:
			((java.util.Map<String,Object>)ActionContext.getContext().get("request")).put(key, value);
			break;
		case SESSION:
			ActionContext.getContext().getSession().put(key, value);
			break;
		case APPLICATION:
			ActionContext.getContext().getApplication().put(key, value);
			break;
		default:
			break;
		}
		
	}	
	
	
	
	
	
	
	/**
	 * 获得当前登录的会员用户
	 * @return
	 */
	protected <T> T getLoginedPersonUser(){
		Object u = ActionContext.getContext().getSession().get(LOGINED_PERSON_USER);
		return u==null?null:(T)u;
	}
	
	/**
	 * 获得当前登录的企业用户
	 * @return
	 */
	protected <T> T getLoginedCorpUser(){
		Object u = ActionContext.getContext().getSession().get(LOGINED_CORP_USER);
		return u==null?null:(T)u;
	}
	
	
	/**
	 * 获得当前登录的运营商用户
	 * @return
	 */
	protected <T> T getLoginedManagerUser(){
		Object u = ActionContext.getContext().getSession().get(LOGINED_MANAGE_USER);
		return u==null?null:(T)u;
	}
	
	
	
	protected HttpServletRequest request;
	protected HttpServletResponse response;
	protected ServletContext servletContext;
	/* *
	 *注入 HttpServletRequest
	 */
	
	public void setServletRequest(HttpServletRequest arg0) {
		// TODO 子类重写
		this.request = arg0;
	}

	/* *
	 * 注入 HttpServletResponse
	 */
	
	public void setServletResponse(HttpServletResponse arg0) {
		// TODO 子类重写
		this.response = arg0;
	}

	/* *
	 * 注入 setServletContext
	 */
	
	public void setServletContext(ServletContext arg0) {
		// TODO 子类重写
		this.servletContext = arg0;
	}
	
	
	
	Map<String,Object> _paramMap = new HashMap<String,Object>();
	/**
	 * 获得表单元素值
	 * @param name
	 * @return
	 */
	public Object getParam(String key){
		if (_paramMap.size()==0){
			Map<String,Object> paramMap = ActionContext.getContext().getParameters();		
			for (Map.Entry<String,Object> kvp : paramMap.entrySet()) {
				_paramMap.put(kvp.getKey().toUpperCase(),kvp.getValue());
			}
		}			
		
		if(!_paramMap.containsKey(key.toUpperCase()))
			return "";
		Object[] values =  (Object[])_paramMap.get(key.toUpperCase());
		if (values==null || values.length==0)
			return "";
		if (values.length==1)
			return values[0]==null?"":values[0];
		return values;	
	}
	
	/**
	 * 绑定参数到对象属性
	 * @param entity
	 * @param params
	 */
	public void bindParam2Bean(Object entity){
		
		Map<String,Object> paramMap = ActionContext.getContext().getParameters();
		if (paramMap==null || paramMap.size()==0)
			throw new InvalidParameterException("没有有效的参数可以绑定");
		Class classzz = entity.getClass();
		//將所有私有字段裝入Map<字段名,字段對象>
		Map<String,Field> fieldMap = new HashMap<String,Field>();
		for (Field f : classzz.getDeclaredFields()) {
			fieldMap.put(f.getName().toUpperCase(),f);
		}
		Field f = null;
		Object fvalue = null;
		for (Map.Entry<String,Object> kvp : paramMap.entrySet()) {
			try {
				Object[] values = (Object[])kvp.getValue();
				if (null != values && values.length==1){
					//f = classzz.getDeclaredField(kvp.getKey());
					f = fieldMap.get(kvp.getKey().toUpperCase());//從HashMap中取得字段對象[不區分大小寫]
					if ( null == f)
					 	continue;
					f.setAccessible(true);
					if (f.getType()==String.class){
						f.set(entity, values[0]);
					}else{
						fvalue = f.getType().getDeclaredMethod("valueOf",String.class).invoke(null, values[0]);
						f.set(entity, fvalue);
					}
						
				}
			} catch (Exception e) {
				if (super.LOG.isInfoEnabled())					
					super.LOG.info(java.text.MessageFormat.format("封装请求参数{0}到JavaBean的{1}属性失败[{2}]", kvp.getKey(),f.getName(),e.getMessage()));
			}
		}
	}

	protected ServiceTemplate serviceTemplate = new ServiceTemplate();
	
	/**
	 * 存放验证的消息
	 */
	private Map<String,String> validateMsgs = new HashMap<String,String>();
	
	protected void addValidateMsg(String msgKey,String msgValue){
		validateMsgs.put(msgKey, msgValue);
		request.setAttribute(VALIDATE_MSG, this.validateMsgs);
	}
	
	protected Boolean isValid(){
		if(this.validateMsgs.size()>0)
			request.setAttribute(VALIDATE_MSG, this.validateMsgs);
		return this.validateMsgs.size()==0;
	}
	
	/**
	 * 獲得客戶端IP
	 * @param request
	 * @return
	 */
	public String getIpAddr(HttpServletRequest request) {
		String ip = request.getHeader("x-forwarded-for");
		if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
		ip = request.getHeader("Proxy-Client-IP");
		}
		if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
		ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
		ip = request.getRemoteAddr();
		}
		return ip;
	}
}


BaseJSONAction源码:

package org.job.web.action;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

import net.it028.foundation.global.ExceptionUtil;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.job.uptl.*;
import org.job.uptl.UProtocol.*;
import org.job.web.convertor.*;


/**
 * 
 * 所有客户端接口请求的Action的基类
 * @author jiangtong
 *
 */
public class BaseJSONAction extends BaseAction {

	static { 
	      ConvertUtils.register(new SqlDateConverter(null), java.sql.Date.class); 
	      ConvertUtils.register(new SqlTimestampConverter(null), java.sql.Timestamp.class); 
	} 

	
	/**
	 * 
	 */
	private static final long serialVersionUID = -3138932274689672883L;

	
	/**
	 * 執行子類Action的模板方法
	 * @param actionCallback
	 * @return
	 */
	public String executeAction(IExecuteActionCallback actionCallback){
		String result = super.SUCCESS;
		try {
			getUp().status = ERspStatus.Success;
			if (actionCallback!=null)
				result = actionCallback.execute(this);
			getUp().msg = "success";
		}catch (Exception e2) {
			getUp().status = ERspStatus.Exception;			
			getUp().msg=ExceptionUtil.getMsg(e2);
			if (getUp().msg.contains("ConstraintViolationException")){
				getUp().msg = "数据项重复录入";
			}
		}
		return result;
	}
	
	/**
	 *通讯协议 
	 */	
	private UProtocol up;

	/**
	 *获得通讯协议 
	 */
	public UProtocol getUp() {
		if (up==null)
			up= new UProtocol();
		return up;
	}

	/**
	 *设置通讯协议 
	 */
	public void setUp(UProtocol up) {
		this.up = up;
	}
	
}


BaseUploadAction源码:

package org.job.web.action;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.UUID;

import net.it028.foundation.global.StringUtils;

import org.apache.struts2.ServletActionContext;

public class BaseUploadAction extends BaseJSONAction {

	private static final long serialVersionUID = 5196594946316620265L;

	private String savePath;
	private File uploadFile;
	private String uploadContentType;
	private String filename;

	/**
	 * 保存路径,通过struts配置文件注入
	 * 
	 * @return
	 */
	public String getSavePath() {
		return ServletActionContext.getRequest().getSession()
				.getServletContext().getRealPath(savePath);
	}

	public void setSavePath(String savePath) {
		this.savePath = savePath;
	}

	/**
	 * 上传的文件
	 * 
	 * @return
	 */
	public File getUploadFile() {
		return uploadFile;
	}

	public void setUploadFile(File uploadFile) {
		this.uploadFile = uploadFile;
	}

	/**
	 * 上传文件的内容类型
	 * 
	 * @return
	 */
	public String getUploadContentType() {
		return uploadContentType;
	}

	public void setUploadContentType(String uploadContentType) {
		this.uploadContentType = uploadContentType;
	}

	/**
	 * 上传的文件名
	 * 
	 * @return
	 */
	public String getFilename() {
		return filename;
	}

	public void setFilename(String filename) {
		this.filename = filename;
	}

	/**
	 * 保存文件
	 */
	protected String saveFile(String filename) {
		String savePath = getSavePath();
		File fileSavePath = new File(savePath);
		if (!fileSavePath.exists() && !fileSavePath.mkdirs()) {// 如果目录不存在则主动创建
			throw new RuntimeException("保存文件前创建目录路径失败......");
		}
		FileOutputStream fos = null;
		FileInputStream fis = null;

		String saveFileName = filename;
		if (filename == null || "".equals(filename))
			saveFileName = StringUtils.getUniqueString()
					+ getFilename().substring(getFilename().lastIndexOf("."));
		try {
			// 以服务器的文件保存地址和源文件名建立上传文件输出流
			fos = new FileOutputStream(savePath + File.separatorChar
					+ saveFileName, false);
			// 以上传文件建立一个文件上传流
			fis = new FileInputStream(getUploadFile());
			// 将上传文件的内容写入服务器
			byte[] buffer = new byte[1024 * 1024];
			int len = 0;
			while ((len = fis.read(buffer)) > 0) {
				fos.write(buffer, 0, len);
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			try {
				if (fos != null) {
					fos.flush();
					fos.close();
				}
				if (fis != null) {
					fis.close();
				}
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}

		return saveFileName;
	}

}


UploadDemoAction源码:

package org.job.enterprice.web;

import java.sql.Timestamp;
import java.util.Date;

import javax.annotation.Resource;

import net.it028.foundation.global.DateUtil;

import org.apache.commons.lang.xwork.StringUtils;
import org.job.uptl.UPDataProtocol;
import org.job.web.action.BaseJSONAction;
import org.job.web.action.BaseUploadAction;
import org.job.web.action.IExecuteActionCallback;

public class UploadDemoAction extends BaseUploadAction {

	private static final long serialVersionUID = -871233872187381L;

	/**
	 * 上传文件示范1
	 * 
	 * @return
	 */
	public String uploadMethod1() {
		return this.executeAction(new IExecuteActionCallback() {
			
			@Override
			public String execute(BaseJSONAction action) {				
				String param1 = getParam("param1").toString();
				
				System.out.println("接收到的上传参数:"+param1);
				
				// 处理文件扩展名
				String fileName = getFilename();
				//取得扩展名
				String exName = fileName.substring(fileName
						.lastIndexOf(".") + 1);
				//新文件名[根据自己的规则生成]
				//String nfilename = DateUtil.getTimestamp().getTime()+"."+exName;
				
				String nfilename = saveFile("");//该方法返回保存后的文件名,如果给定的文件无效将重新生成	
				
				UPDataProtocol up = new UPDataProtocol();
				up.setData(nfilename);
				setUp(up);
				
				return SUCCESS;
			}
		});
	}
}

Struts配置示范:

<package name="corpasyn_demo" namespace="/corpasyn" extends="jobcommon">
<!-- 上传示范 -->
		<action name="UploadAction" class="org.job.enterprice.web.UploadDemoAction">
			<!-- 保存目录 -->
			<param name="savePath">/2</param>
			<!-- 返回格式 -->
			<result type="json">
				<param name="ignoreHierarchy">false</param>
				<param name="root">up</param>
			</result>
			<!-- 系统上传拦截器 -->
			<interceptor-ref name="fileUpload">
				<param name="allowedExtensions">.jpg,.gif,.png,.bmp</param>
				<param name="maximumSize">2097152</param>
			</interceptor-ref>
			<!-- 自定义身份认证拦截器 -->
			<interceptor-ref name="authenInterceptStack"></interceptor-ref>
		</action>
		
</package>

瞥一眼jobcommon这个包的关键代码:

<!-- 通用Action -->
	<package name="jobcommon" namespace="/" extends="json-default">
		<interceptors>
			<interceptor name="authenticationInterceptor" class="org.job.web.interceptor.AuthenticationInterceptor" />
			<!-- 自定义拦截器需要和缺省拦截器栈整合,否则可能丢失struts2的一些既定功能,比如参数赋值-->
			<interceptor-stack name="authenInterceptStack">						
				<interceptor-ref name="defaultStack"></interceptor-ref>
				<interceptor-ref name="authenticationInterceptor"></interceptor-ref>
			</interceptor-stack>			
		</interceptors>
				
		<!--Action的缺省拦截器[身份认证和授权]  -->
		<default-interceptor-ref name="authenInterceptStack" />
</package>


原文地址:https://www.cnblogs.com/riskyer/p/3236989.html