在做B/S架构项目时,经常会遇到文件上传与下载的需求,在struts2框架中帮我们实现的文件上传与下载机制,能够很好地实现项目需求。在使用的时候,需要导入文件上传与下载需要的两个jar,一个是commons-fileupload-x.x.x.jar,另一个是commons-io-x.x.x.jar.
一、文件上传的表单(多文件上传)
在做文件上传时,表单中的method方法必须是post,里边的enctype必须是multipart/form-data。不然会出现莫名其妙的异常。多文件上传的表单通过js技术来做控制。整个上传文件的页面是:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61<%@ page language="java" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s"%> <script type="text/javascript" language="JavaScript" src="${pageContext.request.contextPath }/script/calendar.js" charset="gb2312"></script> <script language="javascript"> function checkf() { var files = document.getElementsByName("file"); if (files[0].value.length != 0) { return true; } else { alert("请选择文件"); return false; } } //添加一行 function addMore() { var td = document.getElementById("more"); //换行 var br = document.createElement("br"); var input = document.createElement("input"); var button = document.createElement("input"); input.type = "file"; input.name = "file"; button.type = "button"; button.value = "Remove"; button.onclick = function() { td.removeChild(br); td.removeChild(input); td.removeChild(button); } td.appendChild(br); td.appendChild(input); td.appendChild(button); } </script> <html> <head> <title>测试文件上传的jsp</title> <link href="${pageContext.request.contextPath }/css/Style.css" type="text/css" rel="stylesheet"> </head> <body> <s:form action="upLoadAction_upload.do" method="post" theme="simple" enctype="multipart/form-data"> <table align="center" width="50%" border="1"> <tr> <td>选择上传文件</td> <td id="more"><s:file name="file"></s:file> <input type="button" value="Add More.." οnclick="addMore()"></td> </tr> <tr> <td><s:submit type="button" value="submit" οnclick="return checkf()" /></td> <td><s:reset value="reset "></s:reset></td> </tr> </table> </s:form> </body> </html>
二、文件上传的Action
在文件上传的action中必须要有三个参数,分别是File类型的file-上传的文件;String类型的fileFileName-上传文件的名称;String类型的fileContentType-文件类型。如果是多文件上传,使用List集合去包裹,也就是List<File> file-上传文件集合;List<Sting> fileFileName-文件名称集合;List<String> fileContentType-文件类型集合。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132package cn.ysu.zhy.devmanager.action; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.struts2.ServletActionContext; import org.springframework.stereotype.Controller; @Controller("upLoadAction") public class UpLoadAction extends BaseAction { /** * 1.做文件上传必须得三个参数:file,fileFileName,fileContentType */ /** * 对应jsp的file标签,表示上传的文件(多文件用集合表示) */ private List<File> file; /** * 文件名称 */ private List<String> fileFileName; /** * 文件的类型 */ private List<String> fileContentType; /** * 2.下载的文件名 */ private String fileName; private String fileUploadErrorMessage; public List<File> getFile() { return file; } public void setFile(List<File> file) { this.file = file; } public List<String> getFileFileName() { return fileFileName; } public void setFileFileName(List<String> fileFileName) { this.fileFileName = fileFileName; } public List<String> getFileContentType() { return fileContentType; } public void setFileContentType(List<String> fileContentType) { this.fileContentType = fileContentType; } public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } /** * @Name: home * @Description: 跳转到上传首页upload.jsp * @Author: ZHY(作者) * @Version: V1.00 (版本号) * @Create Date: 2016-10-07 (创建日期) * @Parameters: 无 * @Return: String 跳转到上传首页upload.jsp */ public String home() { return "home"; } /** * @throws Exception * @Name: upload * @Description: 处理文件的上传 * @Author: ZHY(作者) * @Version: V1.00 (版本号) * @Create Date: 2016-10-07 (创建日期) * @Parameters: 无 * @Return: String 上传成功,重定向到upload.jsp */ public String upload() throws Exception { // 1.获取上传的文件路径 File filePath = new File(ServletActionContext.getServletContext().getRealPath("myUploadFile")); // 2.判断目录是否存在,如果不存在创建文件夹 if (!filePath.exists()) { filePath.mkdir();// 创建目录 } System.out.println(filePath); if (file != null && file.size() > 0 && fileFileName != null && fileFileName.size() > 0) { for (int i = 0; i < file.size(); i++) { // 3.声明文件的输入流,为输入流指定路径 FileInputStream is = new FileInputStream(file.get(i)); // 获取上传文件的大小(单位是字节1257114280--是1.17G),做数据狭小的限制,如果大于209715200,也就是200M,return // error,提示上传文件大小不能超过200M,2097152--2M int length = is.available();// 获取上传文件的字节大小 // 上传的文件超过200M if (length >= 209715200) { request.setAttribute("error", "您上传的文件超过200M"); return "error"; } // 4.获取文件输出流,声明输出流的地址已及名称 FileOutputStream out = new FileOutputStream(filePath + "\" + fileFileName.get(i)); try { // 5.流对接 byte[] buffer = new byte[1024]; int len = 0; while ((len = is.read(buffer)) > 0) { // 将buffer里的二进制数,从0开始,每次写len这么长,写入输出流中 out.write(buffer, 0, len); } } catch (Exception e) { e.printStackTrace(); } finally { is.close(); out.close(); } } } request.setAttribute("fileName", fileFileName); return "upload"; } /** * @Name: upload * @Description: 处理文件的下载 * @Author: ZHY(作者) * @Version: V1.00 (版本号) * @Create Date: 2016-10-07 (创建日期) * @Parameters: 无 * @Return: String 下载成功,重定向到upload.jsp */ public String download() { return "download"; } }
三、文件下载的表单
文件下载相对于文件上传要简单一些,在JSP中唯一需要注意的就是中文乱码问题,解决乱码问题使用URLEncoder和URLDecoder基本上就能解决了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34<%@ page language="java" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s"%> <script type="text/javascript" language="JavaScript" src="${pageContext.request.contextPath }/script/calendar.js" charset="gb2312"></script> <html> <head> <title>测试文件下载的jsp</title> <link href="${pageContext.request.contextPath }/css/Style.css" type="text/css" rel="stylesheet"> </head> <body> <table align="center" width="50%" border="1"> <s:if test="#request.fileName != null && #request.fileName.size() > 0"> <s:iterator value="#request.fileName" var="name"> <s:set value="name" id="names" name="names" scope="Request" /> <% //没有进行编码 String fname = (String) request.getAttribute("names"); //编码之后的值 String fnameEncode = java.net.URLEncoder.encode(fname, "UTF-8"); %> <tr> <td><%=fname%></td> <td><a href="<s:url value='downLoadAction_download.do'><s:param name='fileName'><%=fnameEncode%></s:param> </s:url>">下载</a> </td> </tr> </s:iterator> </s:if> </table> </body> </html>
四、文件下载的Action
在文件下载的action中,必须有两个参数,一个是String类型的fileName-文件名称和InputStream类型的fileInput-文件下载的流。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81package cn.ysu.zhy.devmanager.action; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import org.apache.struts2.ServletActionContext; import org.springframework.stereotype.Controller; /** * 文件下载的action * * @author ZHY * */ @Controller("downLoadAction") public class DownLoadAction extends BaseAction { /** * 下载文件的名称 */ private String fileName; /** * 下载的文件 */ private InputStream fileInput; public String getFileName() { return fileName; } public void setFileName(String fileName) { try { fileName = new String(fileName.getBytes("ISO8859-1"), "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } this.fileName = fileName; } public InputStream getFileInput() { try { fileName = URLDecoder.decode(fileName, "UTF-8"); } catch (Exception e) { e.printStackTrace(); } return ServletActionContext.getServletContext().getResourceAsStream("myUploadFile\" + fileName); } public void setFileInput(InputStream fileInput) { this.fileInput = fileInput; } /** * 下载时,显示中文名字 * */ public String getDownloadFileName() { String downloadFileName = fileName; try { // 使用ISO8859-1编码 downloadFileName = new String(downloadFileName.getBytes(), "ISO8859-1"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return downloadFileName; } /** * @Name: download * @Description: 处理文件的上传 * @Author: ZHY(作者) * @Version: V1.00 (版本号) * @Create Date: 2016-10-07 (创建日期) * @Parameters: 无 * @Return: String 上传成功,重定向到upload.jsp */ public String download() { try { fileName = URLDecoder.decode(fileName, "UTF-8"); } catch (Exception e) { e.printStackTrace(); } fileInput = ServletActionContext.getServletContext().getResourceAsStream("myUploadFile\" + fileName); if (fileInput == null) { return "error"; } return "download"; } }
1
2<!-- 允许文件上传的大小,默认为2M 2097152 在这里设置成自己想要的--> <constant name="struts.multipart.maxSize" value="2097152"></constant>
五、超出指定上传文件大小之后的提示
在项目中,往往有这种需求:当用户上传的文件大于系统设定的值的时候,需要提示用户,如果直接报错,用户体验非常不好。我在做这部分需求的时候,走了不少弯路,也查阅了大量的网上的资料,但是最终还是遇到了一个跨不过去的坑(对于我来说的,可能是自己知识储备不到位)。
我查阅了很多资料,都是说需要重写action中的addActionError方法,将上传文件的错误转变成action级别的错误,我这样做了,也在addActionError中获取到了相应的文件大小,将错误信息添加到supper.addActionError中之后,无论我如何,在jsp中也获取不到我自己抛出的错误信息,而是页面直接报错了。这个问题困扰了我很久,也跟一些人讨论过,但是最终还是没有一个完美的解释。于是,我想了一个比较笨的方法:
1、首先在constant中配置一个很大的最大值,这个值可以设置的大一点,我这里设置成了2000M;
PS:我主要是最文档文件上传,也就是一些doc、pdf等,一帮不可能超过这么大。我系统中的需求是不能大于200M。
2、在文件上传的action中,获取上传上来的文件的大小,跟200M做一个比较,如果大于200M,那么将错误信息写到request作用域中,然后return error。否则正常执行文件上传的操作。对应代码中的位置:
1
2
3
4
5
6
7
8
9
10// 声明文件的输入流,为输入流指定路径 FileInputStream is = new FileInputStream(file.get(i)); // 获取上传文件的大小(单位是字节1257114280--是1.17G),做数据狭小的限制,如果大于209715200,也就是200M,return // error,提示上传文件大小不能超过200M,2097152--2M int length = is.available();// 获取上传文件的字节大小 // 上传的文件超过200M if (length >= 209715200) { request.setAttribute("error", "您上传的文件超过200M"); return "error"; }
1<s:property value="#request.error" />
点我下载Demo
最后
以上就是欢喜大船最近收集整理的关于struts2文件的上传与下载--超出指定文件大小的校验提示一、文件上传的表单(多文件上传)二、文件上传的Action三、文件下载的表单四、文件下载的Action五、超出指定上传文件大小之后的提示的全部内容,更多相关struts2文件内容请搜索靠谱客的其他文章。
发表评论 取消回复