struts2 文件上传下载
四、文件的上传(拦截器)和下载(stream结果类型)(需要练一遍)
1、文件上传
必要前提:
a.表单method必须是post;
b.enctype取值必须是multipart/form-data;
c.提供文件选择域。
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 <%@ taglib uri="/struts-tags" prefix="s" %> 3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 4 <html> 5 <head> 6 <title>struts2中的文件上传</title> 7 </head> 8 <body> 9 <%--文件上传的必要前提: 10 1.请求方式必须是post 11 2.enctype属性的取值必须是multipart/form-data 12 3.提供一个文件选择域 13 --%> 14 <s:actionerror/> 15 <s:form action="upload.action" enctype="multipart/form-data"> 16 <s:textfield name="username" label="用户名" /> 17 <s:file name="photo" label="照片" /> 18 <s:submit value="上传"/> 19 </s:form> 20 </body> 21 </html>
动作类:
1 /** 2 * struts2文件上传的入门案例 3 * @author zhy 4 * 5 */ 6 public class UploadAction extends ActionSupport { 7 8 //表单上提供的字段 9 private String username; 10 private File photo; 11 //struts2在文件上传时提供的属性 12 private String photoFileName;//上传的文件名。上传字段名称+FileName 注意大小写 13 private String photoContentType;//上传文件的MIME类型。上传字段名称+ContentType 注意大小写 14 15 16 public String upload(){ 17 //1.拿到ServletContext 18 ServletContext application = ServletActionContext.getServletContext(); 19 //2.调用realPath方法,获取根据一个虚拟目录得到的真实目录 20 String filePath = application.getRealPath("/WEB-INF/files"); 21 //3.如果这个真实的目录不存在,需要创建 22 File file = new File(filePath); 23 if(!file.exists()){ 24 file.mkdirs(); 25 } 26 //4.把photo存过去 27 //拷贝:把photo的临时文件复制到指定的位置。注意:临时文件还在 28 //FileUtils.copyFile(photo, new File(file,photoFileName)); 29 30 //剪切:把临时文件剪切指定的位置,并且给他重命名。 注意:临时文件没有了 31 photo.renameTo(new File(file,photoFileName)); 32 33 return null; 34 } 35 36 37 public String getUsername() { 38 return username; 39 } 40 41 42 public void setUsername(String username) { 43 this.username = username; 44 } 45 46 47 public File getPhoto() { 48 return photo; 49 } 50 51 52 public void setPhoto(File photo) { 53 this.photo = photo; 54 } 55 56 57 public String getPhotoFileName() { 58 return photoFileName; 59 } 60 61 62 public void setPhotoFileName(String photoFileName) { 63 this.photoFileName = photoFileName; 64 } 65 66 67 public String getPhotoContentType() { 68 return photoContentType; 69 } 70 71 72 public void setPhotoContentType(String photoContentType) { 73 this.photoContentType = photoContentType; 74 } 75 76 77 }
2、文件上传的配置
2.1、文件上传大小限制(默认是2MB)
如果上传文件超过了默认大小,upload拦截器会转向一个input的逻辑视图。
如果 input视图返回了登陆页面, 可以使用<s:actionerror/> 回显错误信息
a、改变上传文件大小限制:
思路1:给Struts2的拦截器注入参数:(行不通)
思路2:在struts.xml中改变default.properties文件中的常量。
1 <!-- 配置全局消息资源包 --> 2 <constant name="struts.custom.i18n.resources" value="com.itheima.web.action.fileupload_message"></constant> 3 <!-- 限制上传文件的大小,第一种方式:通过修改struts2的常量。 4 在default.properties中配的struts.multipart.maxSize=2097152--> 5 <constant name="struts.multipart.maxSize" value="5242880"></constant> 6 <package name="p1" extends="struts-default"> 7 <action name="upload" class="com.itheima.web.action.UploadAction" method="upload"> 8 <!-- 第二种方式:通过给fileUpload的拦截器注入参数的形式,控制上传文件的大小 9 无法使用 <param name="fileUpload.maximumSize">31457280</param>--> 10 <interceptor-ref name="defaultStack"> 11 <!-- 限制上传文件的扩展名。如果有多个,使用逗号分隔 12 <param name="fileUpload.allowedExtensions">jpg,png,bmp</param>--> 13 <!-- 限制上传文件的MIME类型。 如果有多个,使用逗号分隔 --> 14 <param name="fileUpload.allowedTypes">image/jpg,image/pjpeg,image/png</param> 15 </interceptor-ref> 16 <result name="input">/upload1.jsp</result> 17 </action>
2.2、限制文件上传的类型
a、通过限制上传文件的扩展名
思路:给fileUpload拦截器注入参数
当上传非限定扩展名时:有如下错误提示(英文提示)
b、通过限制上传文件的MIME类型
当上传非限定MIME类型时:有如下错误提示(英文提示)
<!-- 配置全局消息资源包 --> <constant name="struts.custom.i18n.resources" value="com.itheima.web.action.fileupload_message"></constant> <!-- 限制上传文件的大小,第一种方式:通过修改struts2的常量。 在default.properties中配的struts.multipart.maxSize=2097152--> <constant name="struts.multipart.maxSize" value="5242880"></constant> <package name="p1" extends="struts-default"> <action name="upload" class="com.itheima.web.action.UploadAction" method="upload"> <!-- 第二种方式:通过给fileUpload的拦截器注入参数的形式,控制上传文件的大小 无法使用 <param name="fileUpload.maximumSize">31457280</param>--> <interceptor-ref name="defaultStack"> <!-- 限制上传文件的扩展名。如果有多个,使用逗号分隔 <param name="fileUpload.allowedExtensions">jpg,png,bmp</param>--> <!-- 限制上传文件的MIME类型。 如果有多个,使用逗号分隔 --> <param name="fileUpload.allowedTypes">image/jpg,image/pjpeg,image/png</param> </interceptor-ref> <result name="input">/upload1.jsp</result> </action>
3、出错后的错误信息中文提示(Struts2中的所有文本提示都是基于国际化的)
默认信息提示在:struts2-core.jar\org.apache.struts2\struts-message.properties
解决办法:用国际化消息资源包,把对应的key取值改为中文即可。
常用的key值:
4、多文件上传
jsp页面:
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 <%@ taglib uri="/struts-tags" prefix="s" %> 3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 4 <html> 5 <head> 6 <title>struts2中的多文件上传</title> 7 </head> 8 <body> 9 <%--文件上传的必要前提: 10 1.请求方式必须是post 11 2.enctype属性的取值必须是multipart/form-data 12 3.提供一个文件选择域 13 --%> 14 <s:actionerror/> 15 <s:form action="upload1.action" enctype="multipart/form-data"> 16 <s:textfield name="username" label="用户名" /> 17 <s:file name="photo" label="照片" /> 18 <s:file name="photo" label="照片" /> 19 <s:submit value="上传"/> 20 </s:form> 21 </body> 22 </html>
配置文件:
1 <action name="upload1" class="com.itheima.web.action.UploadAction1" method="upload"> 2 <result name="input">/upload2.jsp</result> 3 </action>
动作类:
1 /** 2 * struts2文件上传的入门案例 3 * @author zhy 4 * 5 */ 6 public class UploadAction1 extends ActionSupport { 7 8 //表单上提供的字段 9 private String username; 10 private File[] photo; 11 //struts2在文件上传时提供的属性 12 private String[] photoFileName;//上传的文件名。上传字段名称+FileName 注意大小写 13 private String[] photoContentType;//上传文件的MIME类型。上传字段名称+ContentType 注意大小写 14 15 16 public String upload(){ 17 //1.拿到ServletContext 18 ServletContext application = ServletActionContext.getServletContext(); 19 //2.调用realPath方法,获取根据一个虚拟目录得到的真实目录 20 String filePath = application.getRealPath("/WEB-INF/files"); 21 //3.如果这个真实的目录不存在,需要创建 22 File file = new File(filePath); 23 if(!file.exists()){ 24 file.mkdirs(); 25 } 26 //4.把photo存过去 27 //剪切:把临时文件剪切指定的位置,并且给他重命名。 注意:临时文件没有了 28 for(int i=0;i<photo.length;i++){ 29 photo[i].renameTo(new File(file,photoFileName[i])); 30 } 31 32 return null; 33 } 34 35 36 public String getUsername() { 37 return username; 38 } 39 40 41 public void setUsername(String username) { 42 this.username = username; 43 } 44 45 46 public File[] getPhoto() { 47 return photo; 48 } 49 50 51 public void setPhoto(File[] photo) { 52 this.photo = photo; 53 } 54 55 56 public String[] getPhotoFileName() { 57 return photoFileName; 58 } 59 60 61 public void setPhotoFileName(String[] photoFileName) { 62 this.photoFileName = photoFileName; 63 } 64 65 66 public String[] getPhotoContentType() { 67 return photoContentType; 68 } 69 70 71 public void setPhotoContentType(String[] photoContentType) { 72 this.photoContentType = photoContentType; 73 } 74 75 }
5、文件下载:其实就是一种结果类型(Stream)
动作类:
1 /** 2 * 文件下载 3 * @author zhy 4 * 5 */ 6 public class DownloadAction extends ActionSupport { 7 8 //注意:在给InputSteam指定名称时,不能使用in 9 private InputStream inputStream; 10 //创建一个文件名的属性 11 private String filename; 12 13 public String download()throws Exception{ 14 //1.找到文件的存储路径 15 String filePath = ServletActionContext.getServletContext().getRealPath("/WEB-INF/files/5.jpg"); 16 //2.把文件读到一个InputStream中 17 inputStream = new FileInputStream(filePath); 18 19 //在返回之前,给filename赋值 20 filename="照片.jpg"; 21 22 //3.返回一个成功 23 return SUCCESS; 24 //4.由一个叫做stream的结果类型为我们把剩下的事情做完。 25 } 26 27 public InputStream getInputStream() { 28 return inputStream; 29 } 30 31 public void setInputStream(InputStream inputStream) { 32 this.inputStream = inputStream; 33 } 34 35 public String getFilename() { 36 return filename; 37 } 38 39 public void setFilename(String filename) { 40 this.filename = filename; 41 } 42 43 44 45 46 }
配置文件:
1 <action name="download" class="com.itheima.web.action.DownloadAction" method="download"> 2 <result name="success" type="stream"> 3 <!-- 给stream的结果类型注入参数:Content-Type --> 4 <param name="contentType">application/octet-stream</param> 5 <!-- 告知客户浏览器以下载的方式打开 6 <param name="contentDisposition">attachment;filename=photo.jpg</param> --> 7 <!-- 使用OGNL表达式,来动态获取文件名 8 ${@java.net.URLEncoder@encode(filename,"UTF-8")} 把${}中间的内容当成一个OGNL表达式来看待 9 --> 10 <param name="contentDisposition">attachment;filename=${@java.net.URLEncoder@encode(filename,"UTF-8")}</param> 11 <!-- 注入字节输入流 :取值要写动作类中set方法的名称,首字母改成小写--> 12 <param name="inputName">inputStream</param> 13 </result> 14 </action>
问题:文件名不能在配置文件中写死,需要根据实际情况获取。
解决办法:上面的代码就是处理过后的