uploadify在struts2下的使用

时间:2023-03-08 18:19:38

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

uploadify在struts2下的使用

uploadify在struts2下的使用

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{
width:80%;
border-width: 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、运行效果:

uploadify在struts2下的使用

uploadify在struts2下的使用

uploadify在struts2下的使用

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

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

uploadify在struts2下的使用uploadify在struts2下的使用

我们要直接使用的是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>