struts2文件上传步骤(struts2实现文件上传功能)

步骤如下:

1.重写、自定义JakartaMultiPartRequest类

package com.hikvision.fileUploadProcess.interceptor;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest;

public class MyJakartaMultiPartRequest extends JakartaMultiPartRequest {
@Override
public void parse(HttpServletRequest servletRequest, String saveDir)
throws IOException {
//什么也不做

}
}
struts2文件上传步骤(struts2实现文件上传功能)

原因:

struts2默认的拦截器中有一个FileUploadInterceptor,它会拦截所有的MultipartRequest,并且将得到的File及相关信息传递给action,因此在action被调用之前,文件上传已经被处理完了,不能引入监听文件写入时文件进度;

struts2处理文件上传使用的是commons-fileupload,因此我们可以使用ProgressListener。注意我们需要在解析请求的时候加入我们的监听器,我们首先想到的是替换掉FileUploadInterceptor,不幸的是 FileUploadInterceptor并不执行解析的任务,实际在FileUploadInterceptor被调用之前,MultipartRequest已经被解析了,文件上传的工作已经完成。而实际上对于所有的文件上传请求,struts2会为其生成一个MultiPartRequestWrapper进行包装,而它维护着一个 MultiPartRequest接口的实例。MultiPartRequest的实现类只有一个 JakartaMultiPartRequest,JakartaMultiPartRequest有一个方法parseRequest,此方法负责解析 request并生成FileItem,即对文件进行读写操作,因此我们可以重写此方法,添加ProgressListener。不幸的是,JakartaMultiPartRequest的很多方法都是private的,我们不能继承它然后重写parseRequest方法,JakartaMultiPartRequest实现了MultiPartRequest接口,我们可以编写一个类,实现 MultiPartRequest接口,替代JakartaMultiPartRequest类的代码全都拷贝过来,并修改parseRequest方法,完成文件的写入与进度的监听。

2.配置struts2.xml

<!– 1配置自定义文件类myRequestParser,继承MultiPartRequest重写 –>
<bean type=”org.apache.struts2.dispatcher.multipart.MultiPartRequest”
name=”myRequestParser” class=”com.hikvision.fileUploadProcess.interceptor.MyJakartaMultiPartRequest”
scope=”default” optional=”true” />

<!– 注意struts2.3.15.1以前版本这里为struts.multipart.handler, struts2.3.15.1(包含2.3.15.1)这里为struts.multipart.parser–>
<constant name=”struts.multipart.parser” value=”myRequestParser” />

<!– 配置项目所上传文件的最大的Size为1000M –>
<constant name=”struts.multipart.maxSize” value=”1048576000″/>

3.定义文件上传进度信息的类

package com.hikvision.fileUploadProcess.entity;

/**
* 上传文件进度信息
*
* @author wanglei
* @version 0.1
*/
public class FileUploadProgress {
// 文件总长度(设置至少为1字节防止前台出现/0的情况)
private long length = 1;
// 已上传的文件长度
private long currentLength = 0;
// 上传是否完成
private boolean isComplete = false;
public long getLength() {
return length;
}
public void setLength(long length) {
this.length = length;
}
public long getCurrentLength() {
return currentLength;
}
public void setCurrentLength(long currentLength) {
this.currentLength = currentLength;
}
public boolean isComplete() {
return isComplete;
}
public void setComplete(boolean isComplete) {
this.isComplete = isComplete;
}

public FileUploadProgress() {
super();
}

}

4.实现ProgressListener接口

package com.hikvision.fileUploadProcess.impl;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.ProgressListener;

import com.hikvision.fileUploadProcess.entity.FileUploadProgress;

/**
* 文件上传进度消息
* @author hongchenjin
*
*/
public class FileUploadListener implements ProgressListener {
private HttpSession session;

public FileUploadListener(HttpServletRequest request) {
session = request.getSession();
FileUploadProgress fileUploadProgress = new FileUploadProgress();
fileUploadProgress.setComplete(false);
session.setAttribute(“fileUploadProgress”, fileUploadProgress);
}

//更新进度情况
@Override
public void update(long readedBytes, long totalBytes, int currentItem) {
//实现文件上传的核心方法
Object attribute = session.getAttribute(“fileUploadProgress”);
FileUploadProgress fileUploadProgress = null;
if(null == attribute){
fileUploadProgress = new FileUploadProgress();
fileUploadProgress.setComplete(false);
session.setAttribute(“fileUploadProgress”, fileUploadProgress);
}else{
fileUploadProgress = (FileUploadProgress)attribute;
}

fileUploadProgress.setCurrentLength(readedBytes);
fileUploadProgress.setLength(totalBytes);
if(readedBytes==totalBytes){
fileUploadProgress.setComplete(true);
}else{
fileUploadProgress.setComplete(false);
}

session.setAttribute(“progress”, fileUploadProgress);
}

}

5.文件上传进度的action

package com.hikvision.modules.guide.action;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;

import com.hikvision.fileUploadProcess.entity.FileUploadProgress;
import com.hikvision.frame.entity.OperateResult;
import com.hikvision.modules.guide.entity.NameToLocalFile;
import com.hikvision.modules.guide.service.GuideService;
import com.hikvision.modules.guide.util.GetSharePathXml;
import com.hikvision.util.AjaxUtil;
import com.opensymphony.xwork2.ActionSupport;

public class GuideUploadAction extends ActionSupport {

private GuideService guideService;

public GuideService getGuideService() {
return guideService;
}

public void setGuideService(GuideService guideService) {
this.guideService = guideService;
}

//文件格式不支持
public void typeNotSupport(){
OperateResult result = new OperateResult(false,””);
result.setResult(false);
result.setMsg(“上传文件最大不能超过100M;支持的格式为exe,png,jpg,gif,bmp,doc,docx,xls,rar,txt,zip,js,css,msi,pptx”);
AjaxUtil.ajaxWrite(result);
}

/**
* 上传文件
*
* @return
*/
public void uploadfile() {
OperateResult result = new OperateResult(false,””);
try {
HttpServletRequest request = ServletActionContext.getRequest();
//获取文件备注
String comments = request.getParameter(“comments”);
//文件上传
UploadFile.upload(request, ServletActionContext.getResponse());
//将文件名和文件的对应关系存进数据库里
NameToLocalFile nameToLocalFile = new NameToLocalFile();
SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-MM-dd hh:mm:ss”);
String time = sdf.format(new Date());
nameToLocalFile.setCreatetime(time);
//保存在服务器上的路径
nameToLocalFile.setLocalpath(“/” request.getParameter(“variety”) “/” request.getParameter(“name”));
nameToLocalFile.setName(request.getParameter(“name”));
nameToLocalFile.setVariety(request.getParameter(“variety”));
nameToLocalFile.setComments(comments);
guideService.saveOrUpdate(nameToLocalFile);
result.setResult(true);
result.setMsg(“上传成功”);
} catch (IOException e) {
LOG.error(“上传文件发生异常,错误原因 : ” e.getMessage());
result.setMsg(“上传文件最大不能超过100M;”);
result.setResult(false);
}
AjaxUtil.ajaxWrite(result);
}

/**
* 修改文件
*/
public void updateNameToLocalFile(){
OperateResult result = new OperateResult(false,””);
HttpServletRequest request = ServletActionContext.getRequest();
//种类
String variety = request.getParameter(“variety”);
//名称
String name = request.getParameter(“name”);
//文件备注
String comments = request.getParameter(“comments”);
//是否上传了文件
Boolean flag = Boolean.parseBoolean(request.getParameter(“flag”));
//id
int id = Integer.parseInt(request.getParameterValues(“ids”)[0]);
//根据id获取数据库的nameToLocalFileById
NameToLocalFile nameToLocalFileById = guideService.getNameToLocalFileById(id);
//分为两种情况,第一种为用户重新上传了文件,第二种是用户只修改了名字和种类
if(flag){
/**
* 用户重新上传文件的情况
*/
//删除原来文件
String localpath = nameToLocalFileById.getLocalpath();
String realPath = GetSharePathXml.getShareFolderPath() localpath;
File file = new File(realPath);
//用户上传了文件
try {

if(file.exists()){
//删除原来文件(判断是否存在该文件,存在就删除)
file.delete();
}

//文件上传
UploadFile.upload(request, ServletActionContext.getResponse());

result.setResult(true);
result.setMsg(“修改成功”);
} catch (Exception e) {
result.setResult(false);
result.setMsg(“修改失败”);
}
}
//将文件名和文件的对应关系存进数据库里
SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-MM-dd hh:mm:ss”);
String time = sdf.format(new Date());
nameToLocalFileById.setCreatetime(time);
if(flag){
//保存在服务器上的路径
nameToLocalFileById.setLocalpath(“/” variety “/” name);
nameToLocalFileById.setName(name);
}
nameToLocalFileById.setVariety(variety);
nameToLocalFileById.setComments(comments);
guideService.saveOrUpdate(nameToLocalFileById);
result.setResult(true);
result.setMsg(“修改成功”);
AjaxUtil.ajaxWrite(result);

}
/**
* 显示上传文件进度进度
*
* @return page view
*/
public void progress() {
// 新建当前上传文件的进度信息对象
FileUploadProgress p = null;
Object attribute = ServletActionContext.getRequest().getSession().getAttribute(“fileUploadProgress”);
if(null == attribute){
p = new FileUploadProgress();
// 缓存progress对象
ServletActionContext.getRequest().getSession().setAttribute(“fileUploadProgress”, p);
}else{
p = (FileUploadProgress)attribute;
}

ServletActionContext.getResponse().setContentType(“text/html;charset=UTF-8”);
ServletActionContext.getResponse().setHeader(“pragma”, “no-cache”);
ServletActionContext.getResponse().setHeader(“cache-control”, “no-cache”);
ServletActionContext.getResponse().setHeader(“expires”, “0”);
//以下方法为输出json(封装,可根据实际情况修改输出的方式)
AjaxUtil.ajaxWriteObject(p);
}

/**
* 清除session
*/
public void clearProgressSession(){
ServletActionContext.getRequest().getSession().setAttribute(“fileUploadProgress”, null);
}
}

6.UploadFile类(文件上传)

package com.hikvision.modules.guide.action;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.log4j.Logger;

import com.hikvision.fileUploadProcess.impl.FileUploadListener;
import com.hikvision.modules.guide.util.GetSharePathXml;
/**
* upload file
*
* @author scott.Cgi
*/
public class UploadFile {
private static final Logger LOG = Logger.getLogger(UploadFile.class);
/**
* 上传文件
*
* @param request
* http request
* @param response
* htp response
* @throws IOException
* IOException
*/
@SuppressWarnings(“unchecked”)
public static void upload(HttpServletRequest request,
HttpServletResponse response) throws IOException {
if (request.getContentType() == null) {
throw new IOException(
“the request doesn’t contain a multipart/form-data stream”);
}

// 上传临时路径
String path = GetSharePathXml.getShareFolderPath();
// 设置上传工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setRepository(new File(path));
// 阀值,超过这个值才会写到临时目录
factory.setSizeThreshold(1024 * 1024 * 10);
ServletFileUpload upload = new ServletFileUpload(factory);
// 最大上传限制
upload.setSizeMax(1024 * 1024 * 1000);
// 设置监听器监听上传进度
upload.setProgressListener(new FileUploadListener(request));
try {
List<FileItem> items = upload.parseRequest(request);

//获取文件类型
String variety = request.getParameter(“variety”);
for (FileItem item : items) {

// 非表单域
if (!item.isFormField()) {
FileOutputStream fos = new FileOutputStream(path “/” variety “/” item.getName());
// 文件全在内存中
if (item.isInMemory()) {
fos.write(item.get());
} else {
InputStream is = item.getInputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
is.close();
}
fos.close();
LOG.info(“完成上传文件!”);

item.delete();
LOG.info(“删除临时文件!”);

LOG.info(“更新progress对象状态为完成状态!”);
}
}
} catch (Exception e) {
LOG.error(“上传文件出现异常, 错误原因 : ” e.getMessage());

request.getSession().removeAttribute(“percent”);
}
}

}

//进度条显示
var everylisten = function() {
//显示进度条
$(“#prosbar”).parent(“div”).css({“display”:”block”});
$.ajax({
url : ‘http://127.0.0.1/guideUpload!progress.action’,
method : ‘GET’,
timeout : 120000,
contentType : “application/json; charset=utf-8”,
dataType : “json”,
success : function(result) {
if(null != result) {
if(result.complete) {
//将进度条长度设为0并隐藏
$(“#prosbar”).css({“width”:”0%”});
clearTimeout(everylisten);
//清除session
clearProgressSession();
}else{
var width = result.currentLength * 100 / result.length “%”;
$(“#prosbar”).css({“width”: width});
setTimeout(everylisten, 500);
}
}else{
alert(data.msg);
}
}
});
};

清除进度条session

//清除session
function clearProgressSession(){
$.ajax({
url : hik.guide.getContextPath() ‘/guideUpload!clearProgressSession.action’,
method : ‘GET’,
timeout : 120000,
contentType : “application/json; charset=utf-8”,
dataType : “json”,
success : function(result) {

}
});
}

$(“#GuideForm”).submit(function(){
everylisten();
return false;
$.ajaxFileUpload
(
{
url:’http://127.0.0.1/guideUpload!uploadfile.action?’
$(“#GuideForm”).serialize(),
secureuri:false,
fileElementId:’upload’,
dataType: ‘json’,
data:{},
success: function (data, status)
{
$(dialogEl).dialog(‘close’);
//上传成功后,提示用户上传成功
if(data.success){
alert(“success”);
}else{
alert(“false”);
}
},
error: function (data, status, e)
{
alert(“出错了”);
}
}
)
});

页面代码(红色部分为必须写的地方):

<form id=”GuideForm” name=”guideForm” action=””
onsubmit=”return false;”
class=”form-horizontal five-columns character5 padding-top8px”
</span><span style=”color:#cc0000;”>enctype=”multipart/form-data”</span><span style=”color:#333333;”> method=”post”>

<div>
<input type=”hidden” name=”ids” >
<div class=”control-group five-columns”>
<label class=”control-label”>文件名称:</label>
<div class=”controls”>
<input class=”span4″ type=”text” name=”name” maxlength=”20″ readonly=”readonly”/>
</div>
</div>
<div class=”control-group five-columns”>
<label class=”control-label”>文件类型:</label>
<div class=”controls”>
<select name=”variety”>
<option value=”tools”>开发工具</option>
<option value=”ecliplse_plugin”>Eclipse常用插件</option>
<option value=”svn”>代码版本控制SVN</option>
<option value=”database”>数据库</option>
<option value=”other”>其他</option>
</select>
</div>
</div>
<div class=”control-group five-columns” style=”display:none;”>
<label class=”control-label”>文件路径:</label>
<div class=”controls”>
<a name=”path” style=”color:blue”></a>
</div>
<div class=”controls”>
<input type=”button” class=”btn btn-primary uploadReset” value=”重新上传” name=”uploadReset”>
</div>
</div>
<div class=”control-group five-columns”>
<div class=”controls”>
<label class=”control-label”>上传文件 :</label>
<input class=”span4″ type=”file”
name=”upload” maxlength=”20″ id=”upload” />
</div>
</div>
<div class=”control-group five-columns”>
<div class=”controls”>
<label class=”control-label”>文件备注:</label>
<textarea rows=”” cols=”” name=”comments” maxLength=”50″></textarea>
</div>
</div>
<div class=”progress progress-striped active” >
<div class=”bar” style=”width: 0%;” id=”prosbar”></div>
</div>
</div>

<!– 上传进度条 –>
</form>

发表评论

登录后才能评论