通常我們在解析form表單提交數據的時候使用FileUpload。但在最近的項目中出現了數據解析不成功的問題。
問題如題,造成這個問題的根本原因是因爲struts2對request對象進行了封裝,由HttpServletRequest變成MultiPartRequestWrapper。導致`fileList = upload.parseRequest(request);`獲取不到上傳的對象所以List爲空。
解決辦法:
1. 更改攔截器
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
改成
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
攔截後綴名可自行定義
2. 修改Struts的配置文件
剔除對Request的封裝
步驟:
a)編寫類文件 繼承類JakartaMultiPartRequest
eg:
public class RequestParseWrapper extends JakartaMultiPartRequest {
public void parse(HttpServletRequest servletRequest, String saveDir)throws IOException {}
}
讓該類生效
在struts.xml(Struts的配置文件,具體名字按照自己項目定義)添加以下內容:
如果struts2的版本是status2.3.4
在配置文件struts.xml里加上
<bean type= "org.apache.struts2.dispatcher.multipart.MultiPartRequest"
name= "myRequestParser" class= "類所在的包路徑.RequestParseWrapper"
scope= "default" optional= "true " />
<constant name= "struts.multipart.handler" value= "myRequestParser" />
如果struts的版本是struts2.3.15.1 以後的版本
在配置文件struts.xml里加上
<bean type= "org.apache.struts2.dispatcher.multipart.MultiPartRequest"
name= "myRequestParser" class= "類所在的包路勁.RequestParseWrapper"
scope= "default" optional= "true " />
<constant name= " struts.multipart.parser" value= "myRequestParser" />
3. 使用MultiPartRequestWrapper
作爲struts更新瞭如此多的版本,依然沒有修復這個問題。具體原因我也不清楚,只是提出解決方案。
下面給出詳細代碼:
jsp頁面:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html>
<html>
<!--[if IE 6]><html class="ie ie6"><![endif]-->
<!--[if IE 7]><html class="ie ie7"><![endif]-->
<!--[if IE 8]><html class="ie ie8"><![endif]-->
<!--[if IE 9]><html class="ie ie9"><![endif]-->
<!--[if gt IE 9]><html> <![endif]-->
<head>
<base href="<%=basePath%>">
<meta charset="UTF-8">
<meta name="renderer" content="webkit">
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
<meta content="width=device-width; initial-scale=1; maximum-scale=1" name="viewport">
<title>發送通知</title>
</head>
<body>
<form enctype="multipart/form-data" name="filesend" id="file-form">
通知標題:<input name="title" type="text" class="title"><br>
通知內容:<textarea rows="10%" cols="50%" name="content" class="content"></textarea><br>
<a href="javascript:;" onclick="javascript:addfile();" class="add-file">添加附件</a>
<div class="ext-file"></div>
</form>
<div class="modal-footer">
<button class="btn btn-primary" onclick="javascript:subimtBtn();">提交</button>
</div>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.form.js"></script>
<script src="js/plugins/layer/layer.min.js"></script>
<script type="text/javascript">
function addfile(){
var br = $("<br>");
var input = $("<input type='file' name='file' />");
var af = $("<a type='button' name='remove' >移除</a>");
$(".ext-file").append(br).append(input).append(af);
af.click(function() {
br.remove();
input.remove();
af.remove();
});
};
function subimtBtn() {
var title="";
title = $(".title").val();
if(title==""){
layer.msg("標題不能爲空!");
return false;
}
var content="";
content = $(".content").val();
if(content==""){
layer.msg("內容不能爲空!");
return false;
}
var ajax_option={
type: "post",
url:"<%=basePath%>/message/notice!getMesg.ac",
dataType: "json",
success:function(data){
console.log(data)
}
}
$('#file-form').ajaxSubmit(ajax_option);
return ;
}
</script>
</body>
</html>
Action方法:
private static final List<String> FILEEXT = Arrays.asList("xls", "xlsx", "doc","docx","jpg","gif","png");//允許的文件格式
private static SimpleDateFormat DF = new SimpleDateFormat("ddHHmmss");//重新格式化的文件名
private static final int FILESIZE = 5*1024*1024;//單個文件最大5M
private String getFileDir(){
if(FILEDIR.isEmpty()){
FILEDIR = getFilepath()+"/upload";
}
return FILEDIR;
}
private String getFilepath(){
if(FILEPATH.isEmpty()){
String classPath = NoticeAction.class.getClassLoader().getResource("/").getPath();
String rootPath = "";
if("\\".equals(File.separator)){//windows下
rootPath = classPath.substring(1,classPath.indexOf("/WEB-INF/classes"));
FILEPATH = rootPath.replace("/", "\\");
}else if("/".equals(File.separator)){//linux下
rootPath = classPath.substring(0,classPath.indexOf("/WEB-INF/classes"));
FILEPATH = rootPath.replace("\\", "/");
}
}
return FILEPATH;
}
public void getMesg()throws Exception{
try {
if (ServletFileUpload.isMultipartContent(request())) {
MultiPartRequestWrapper wrapper = (MultiPartRequestWrapper) request();
String[] filanames = wrapper.getFileNames("file");//所有的文件名
File[] files = wrapper.getFiles("file");//上傳的所有文件
String title = String.valueOf(wrapper.getAttribute("title"));
if (!new File(getFileDir()).isDirectory()){//文件夾上傳目錄
new File(getFileDir()).mkdirs();
}
for(int i=0;i<files.length;i++){
File file = files[i];
String fileName = filanames[i];
//檢查文件大小
if(file.length() > FILESIZE){
WriterJson(false, "", "操作失敗:文件"+fileName+"大小超出最大限度!");
return ;
}
//檢查擴展名
String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
if(!FILEEXT.contains(fileExt)){
WriterJson(false, "", "操作失敗:文件格式不正確");
return;
}
String newFileName = fileName+"_"+DF.format(new Date()) + "_" + new Random().nextInt(1000) +i+ "." + fileExt;//重命名文件名
try {
InputStream in = new FileInputStream(file);
File uploadFile = new File(getFileDir(), newFileName);
OutputStream out = new FileOutputStream(uploadFile);
byte[] buffer = new byte[1024 * 1024];
int length;
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
in.close();
out.close();
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}else{
WriterJson(false, "", "類型不支持!");
}
}catch (Exception e) {
e.printStackTrace();
}
WriterJson(true, "", "操作成功!");
}
其中WriterJson爲項目封裝的Ajax返回。
操作截圖:
相關js文件如下:
jquery.form.js 自己上傳,可自行搜索下載
layer.min.js 請移步官網下載