Struts2基础学习(六)—文件的上传和下载
一、文件的上传
1.单个文件上传
Struts2使用拦截器完成了文件的上传,而且底层使用的也是FileUpload开源组件。
客户端注意事项:
(1)method="post"
(2)enctype="multipart/form-data"
(3)<intput type="file" name="photo">
在Action编写文件上传时,需要定义三个属性。
(1)文件类型File,属性名与表单中的file的name属性名一致。
(2)字符串类型,属性名: name属性名 + FileName eg: photoFileName 。
(3)字符串类型,属性名: name属性名 + ContentType eg: photoContentType 。
最后要为上述的三个属性名提供getXXX 和SetXXX方法。然后通过FileUtils的copyFile方法进行文件复制,将文件上传到服务器。
index.jsp
<s:form action="uploadOne" method="post" enctype="multipart/form-data"> <s:textfield name="username" label="用户名"/> <s:file name="photo" label="照片"/> <s:submit value="上传"/> </s:form>
UploadAction.java
public class UploadAction extends ActionSupport{ private String username; private File photo; private String photoFileName;// 上传的文件名 private String photoContentType;// 上传的文件的MIME类型 public String uploadOne() throws IOException{ System.out.println("username = " + username + "\nphotoName = " + photoFileName + "\nphotoContentType = " + photoContentType); // 上传 String storeDir = ServletActionContext.getServletContext().getRealPath("/upload"); FileUtils.copyFile(photo,new File(storeDir,photoFileName)); return SUCCESS; } public String getPhotoFileName(){ return photoFileName; } public void setPhotoFileName(String photoFileName){ this.photoFileName = photoFileName; } public String getPhotoContentType(){ return photoContentType; } public void setPhotoContentType(String photoContentType){ this.photoContentType = photoContentType; } public String getUsername(){ return username; } public void setUsername(String username){ this.username = username; } public File getPhoto(){ return photo; } public void setPhoto(File photo){ this.photo = photo; } }
结果:
2.文件上传存在的问题
文件上传总大小默认是2M,如果超过了2M,程序会报异常,可使用<s:actionError>查看具体信息。
(1)解决总大小的设置,找到常量
struts.multipart.parser=jakarta 默认文件上传解析器,就是FileUpload组件
struts.multipart.saveDir= 文件上传的临时文件存储目录
struts.multipart.maxSize=2097152 文件上传的最大值(总大小),默认是2M
在struts.xml设置常量,修改文件上传的默认总大小
<!-- 配置上传文件的大小 --> <constant name="struts.multipart.maxSize" value="5000000"/>
(2)还可以通过配置拦截器来设置文件上传
<action name="uploadOne" class="com.kiwi.action.UploadAction" method="uploadOne"> <interceptor-ref name="fileUpload"> <!-- 配置允许上传的文件类型,多个用","分隔 --> <param name="allowedTypes"> image/bmp,image/png,image/gif,image/jpeg,image/jpg ,image/x-png,image/pjpeg </param> <!-- 配置允许上传的文件大小,单位字节 --> <param name="maximumSize">102400</param> </interceptor-ref> <interceptor-ref name="defaultStack" /> <result name="success">/success.jsp</result> </action>
(3)修改显示错误信息的资源文件信息
第一步:创建新的资源文件例如message_zh_CN.properties,放置在src下在该资源文件中增加如下信息:
struts.messages.error.uploading=上传错误: {0}
struts.messages.error.file.too.large=上传文件太大: {0} "{1}" "{2}" {3}
struts.messages.error.content.type.not.allowed=上传文件的类型不允许: {0} "{1}" "{2}" {3}
struts.messages.error.file.extension.not.allowed=上传文件的后缀名不允许: {0} "{1}" "{2}" {3}
第二步:在struts.xml文件加载该资源文件
<constant name="struts.custom.i18n.resources" value="message"/>
3.多文件上传
在JSP的页面上提供多组文件上传的输入框,选择多个文件上传。
index.jsp
<s:form action="uploadOne" method="post" enctype="multipart/form-data"> <s:textfield name="username" label="用户名"/> <s:file name="photo" label="照片1"/> <s:file name="photo" label="照片2"/> <s:file name="photo" label="照片3"/> <s:submit value="上传"/> </s:form>
UploadAction.java
public class UploadAction2 extends ActionSupport{ private String username; private File[] photo; private String[] photoFileName;// 上传的文件名 private String[] photoContentType;// 上传的文件的MIME类型 public String uploadOne() throws IOException{ // 上传 String storeDir = ServletActionContext.getServletContext().getRealPath("/upload"); if(photo != null && photo.length > 0){ for(int i = 0;i < photo.length;i++){ FileUtils.copyFile(photo[i],new File(storeDir,photoFileName[i])); } } return SUCCESS; } public String getUsername(){ return username; } public void setUsername(String username){ this.username = username; } public File[] getPhoto(){ return photo; } public void setPhoto(File[] photo){ this.photo = photo; } public String[] getPhotoFileName(){ return photoFileName; } public void setPhotoFileName(String[] photoFileName){ this.photoFileName = photoFileName; } public String[] getPhotoContentType(){ return photoContentType; } public void setPhotoContentType(String[] photoContentType){ this.photoContentType = photoContentType; } }
二、文件的下载
index.jsp
<s:a action="download?filename=1.jpg">1.jpg</s:a> <br> <s:a action="download?filename=2.jpg">2.jpg</s:a><br> <s:a action="download?filename=3.jpg">3.jpg</s:a><br>
struts.xml
<!-- 文件下载 --> <action name="download" class="com.kiwi.action.DownloadAction"> <result name="success" type="stream"> <!-- 设置文件名称的MIME类型,值不是固定的,值是动态的 --> <param name="ContentType">${contentType}</param> <!-- 设置弹出下载的窗口,文件名称是动态的值 --> <param name="ContentDisposition">attachment;filename=${downloadFilename}</param> </result> </action>DownloadAction.java
public class DownloadAction extends ActionSupport{ //接受文件的名称 private String filename; /* * get请求的中文乱码问题需要自己解决 */ public void setFilename(String filename) throws UnsupportedEncodingException{ this.filename = new String(filename.getBytes("ISO-8859-1"),"UTF-8"); } /* * 提供一个方法,能获取的文件的MIME类型 */ public String getContentType(){ return ServletActionContext.getServletContext().getMimeType(filename); } /* * 返回的是文件的名称 * 在弹出的下载窗口中,显示中文会有乱码的问题 * 判断浏览器,根据不同的编码解决乱码的问题 */ public String getDownloadFilename() throws IOException{ // 先获取user-agent头信息 String agent = ServletActionContext.getRequest().getHeader("user-agent"); // 调用该方法,编码 String name = this.encodeDownloadFilename(filename, agent); return name; } /* * 根据user-agent的头,和文件的名称,解决中文文件名编码的问题 */ public String encodeDownloadFilename(String filename, String agent) throws IOException{ if(agent.contains("Firefox")){ // 火狐浏览器 filename = "=?UTF-8?B?"+new BASE64Encoder().encode(filename.getBytes("utf-8"))+"?="; }else{ // IE及其他浏览器 filename = URLEncoder.encode(filename,"utf-8"); } return filename; } /* * 提供一个方法名称必须是getInputStream()方法 */ public InputStream getInputStream(){ // 获取要下载的文件的输入流,返回 return ServletActionContext.getServletContext().getResourceAsStream("/download/"+filename); } @Override public String execute() throws Exception{ return SUCCESS; } }
结果: