`

struts2-上传与下载

    博客分类:
  • Java
阅读更多

关于struts2-上传与下载(转载)

 

一、struts2的上传下载是如何实现的?

:其实struts2框架中的下载是基于commons.fileupload.jar 和 commons.io.jar来实现的它只是将某些复

   杂的逻辑代码封装起来,并且简化从而利于开发者的开发。

 

二、struts2上传下载的核心是怎么样的?

  1.struts2上传下载的核心是由commons.fileupload中的ServletFileUpload和DiskFileItemFactory类

  来实现(在commons.fileupload.jar中以前的版本,主要使用的是FileUpload类。新的版本提倡使用  FileUpload的子类ServletFileUpload)

 

  2.DiskFileItemFacotry需要设置两个参数

   :Repository:创建一个文件上传的缓存目录

   SizeThreshold:设置在缓存中的文件大小

  

  3.ServletFileUpload实现它的一个有参构造方法

   :参数为FileItemFactory(它是一个接口) DiskFileItemFactory实现了这个接口

   :通过ServletFileUpload类的parseRequest()方法获取一个List<FileItem>集合,通过对集合的遍历解

    析获取表单中的信息

 

  4.下面提供一个以Servlet和jsp 使用commons.fileupload 和commons.io 实现的上传功能

   Servlet:(UploadServlet)

 

package org.viancent.servlet;

Java代码  收藏代码
  1. import java.io.File;  
  2. import java.io.FileOutputStream;  
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.io.OutputStream;  
  6. import java.util.List;  
  7. import javax.servlet.ServletException;  
  8. import javax.servlet.http.HttpServlet;  
  9. import javax.servlet.http.HttpServletRequest;  
  10. import javax.servlet.http.HttpServletResponse;  
  11. import org.apache.commons.fileupload.FileItem;  
  12. import org.apache.commons.fileupload.FileUpload;  
  13. import org.apache.commons.fileupload.FileUploadException;  
  14. import org.apache.commons.fileupload.disk.DiskFileItemFactory;  
  15. import org.apache.commons.fileupload.servlet.ServletFileUpload;  
  16.   
  17. public class UploadServlet extends HttpServlet {  
  18.     @Override  
  19.     @SuppressWarnings("unchecked")  
  20.     protected void doPost(HttpServletRequest req, HttpServletResponse resp)  
  21.             throws ServletException, IOException {  
  22.         /* 
  23.          * 注意,当jsp中表单的enctype设置的为:multipart/form-data的时候 我们无法直接使用 
  24.          * request.getParameter("") 获取表单的数据信息 
  25.          */  
  26.         // 使用DiskFileItemFacotry类进行表单的处理,以及文件的上传  
  27.         DiskFileItemFactory disk = new DiskFileItemFactory();  
  28.         // 获取WebRoot目录下的upload文件夹的路径  
  29.         String path = req.getRealPath("/upload");  
  30.         disk.setRepository(new File(path));// 设置上传文件的缓存目录  
  31.         disk.setSizeThreshold(1024 * 1024); // 设置文件的大小,如果超过这个大小,文件则会直接向硬盘存入  
  32.   
  33.         // 借助ServletFileUpload 进行表单的解析,与文件的流的处理  
  34.         ServletFileUpload upload = new ServletFileUpload(disk);  
  35.         try {  
  36.             List<FileItem> list = upload.parseRequest(req);  
  37.             // List<FileItem>中保存着有关表单元素的所有信息 需要对它进行遍历  
  38.             for (FileItem item : list) {  
  39.                 // item.isFormField() 判断该元素是不是表单的一个字段 如果是 则可以直接取得它的名称和内容  
  40.                 if (item.isFormField()) {  
  41.                     String name = item.getFieldName();  
  42.                     /* 
  43.                      * 获取该字段的名称 如:<input type="text" name="password"/> 
  44.                      * 该方法便是获取name属性的值 :password 
  45.                      */  
  46.                     String value = item.getString("gbk");  
  47.                     /* 获取该字段的value属性的值 */  
  48.                     req.setAttribute(name, value);  
  49.                 } else// else则证明它是一个file文件流  
  50.                 {  
  51.                     String name = item.getFieldName();  
  52.                     String value = item.getName();  
  53.                     /* 
  54.                      * 对于表单中的file元素,我们不能通过getString获取它的内容,因为它是一个流 
  55.                      * 只能够通过getName方法获取当前文件的名称 
  56.                      */  
  57.                     int start = value.lastIndexOf("\\");  
  58.                     // 对value进行处理,由于某些浏览器 可能只显示 文件名+后缀  
  59.                     // 有的则将文件的全部路径都显示出来 ,所以我们要在这里对它进行一次通用处理  
  60.                     String filename = value.substring(start + 1);  
  61.                     // 记住一定要将start+1 因为start的位置对应的是'\\'  
  62.                     req.setAttribute(name, filename);  
  63.                     // 创建输入流 与 输出流  
  64.                     InputStream input = item.getInputStream();  
  65.                     byte[] buffer = new byte[1024];  
  66.                     int length = 0;  
  67.                     OutputStream os = new FileOutputStream(new File(path,  
  68.                             filename));  
  69.                     // 开始读取并写入信息  
  70.                     while ((length = input.read(buffer)) > 0) {  
  71.                         os.write(buffer, 0, length);  
  72.                     }  
  73.                     // 一次关闭流  
  74.                     os.close();  
  75.                     input.close();  
  76.                     // 上传完毕  
  77.                     System.out.println("Upload Over!");  
  78.                 }  
  79.             }  
  80.         } catch (FileUploadException e) {  
  81.             // TODO Auto-generated catch block  
  82.             e.printStackTrace();  
  83.         }  
  84.   
  85.         // 请求转发  
  86.         req.getRequestDispatcher("/upload/result.jsp").forward(req, resp);  
  87.     }  
  88. }  

  Jsp:(upload.jsp)

Java代码  收藏代码
  1. <form action="/struts2/upload" method="post"  
  2.     enctype="multipart/form-data">  
  3.     //一定要设置form表单的 //method属性和enctype实行 UserName:<input type="text"  
  4.         name="username" id="username" /><br /> Password:<input type="password"  
  5.         name="password" id="password" /><br /> File: <input type="file"  
  6.         name="file" id="file" /><br /> <input type="submit" value="submit" />  
  7. </form>  

 

 三、如何使用struts2封装后的上传与下载

: 1.上传

a):对于struts2中的上传主要是由struts-default.xml中名为:fileUpload的拦截器实现的通过拦截客户
端的请求,获取数据信息实现上传功能。
b):实现的主要步骤
1.我们需要创建一个对应上传的Action,在Action中我们需要定义三个字段用于存储表单中文件的信息
如下:
如果页面(<input type="file" name="upload">表单中的file元素名为:upload,那么我们需要在
Action中定义如下字段
private File upload;//对应文件流  根据表单的中的file元素的name属性值命名
private String uploadFileName;  //对应文件的名称 表单name属性值+FileName
private String uploadContentType; //对应文件的类型 表单name属性值+ContentType
/*命名规范是固定,并且要实现它们的getter 和 setter方法 可以参看fileUpload拦截器对应的
        Interceptor类中代码
主要用于拦截器为定义的属性进行赋值,以及后面的调用
*/
2.我们需要在struts.xml 文件中配置一个对应上传的<Action>
如下:
在定义的Action标签中需要添加名为 fileUpload的拦截器,并为它的属性进行赋值。
Java代码  收藏代码
  1. <interceptor ref="fileUpload">  
  2. //可以设置 上传文件的类型,最大大小,  
  3. /* 
  4. 在FileUploadInterceptor 源代码中 有如下片段实例 
  5.  * <ul> 
  6.  * <p/> 
  7.  * <li>maximumSize (optional) - the maximum size (in bytes) that the interceptor will allow a file reference to be set 
  8.  * on the action. Note, this is <b>not</b> related to the various properties found in struts.properties. 
  9.  * Default to approximately 2MB.</li> 
  10.  * <p/> 
  11.  * <li>allowedTypes (optional) - a comma separated list of content types (ie: text/html) that the interceptor will allow 
  12.  * a file reference to be set on the action. If none is specified allow all types to be uploaded.</li> 
  13.  * <p/> 
  14.  * <li>allowedExtensions (optional) - a comma separated list of file extensions (ie: .html) that the interceptor will allow 
  15.  * a file reference to be set on the action. If none is specified allow all extensions to be uploaded.</li> 
  16.  * </ul> 
  17.               
  18.  maximumSize:设置单个上传文件的最大字节,struts2中默认的总上传文件的大小为2097152字节(2M) 我们可以通过 
  19.  <Constant name="struts.multipart.maxSize" value="">value指定大小 ,单位为字节 
  20.  allowedTypes:设置上传文件的类型 上传的文件类型可以参考tomcat中web.xml配置中的文件类型信息 
  21.  属性值 如:application/vnd.ms-powerpoint 代表文件的类型为ppt 
  22.  allowedExtensions:设置文件的扩展名,同上一个属性的效果是一样的,不过它的属性值更加 
  23.  直观易懂 如: .ppt  
  24.  */   
  25.  <param name="allowedExtensions">.ppt,.txt</param>//使用<param>标签进行赋值  
  26.  <param name="maximumSize">409600</param>//上传单个文件的最大字节  
  27.  </interceptor ref>  
 3.一个使用struts2的上传实例:
Action:
Java代码  收藏代码
  1. package org.viancent.action;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.FileOutputStream;  
  6. import java.io.InputStream;  
  7. import java.io.OutputStream;  
  8. import java.util.List;  
  9.   
  10. import org.apache.struts2.ServletActionContext;  
  11.   
  12. import com.opensymphony.xwork2.ActionSupport;  
  13.   
  14. public class UploadAction extends ActionSupport {  
  15.   
  16.     private String username;  
  17.     private String password;  
  18.     /* 
  19.      * 如果每次只上传一个文件 就可以使用上面介绍的代码 
  20.      *  
  21.      * 这里义的泛型集合,是为了上传多个文件,也可以用数组 如: 
  22.      *  privaet File [] file; 
  23.      * private String [] fileFileName; 
  24.      * private String [] fileContentType; 
  25.      */  
  26.     private List<File> file;  
  27.     private List<String> fileFileName;  
  28.     private List<String> fileContentType;  
  29.   
  30.     /* 
  31.      * 为什么要定义fileFileName 和filecontextType 这里是用于FileUpload的拦截器的赋值 
  32.      */  
  33.     public String getUsername() {  
  34.         return username;  
  35.     }  
  36.   
  37.     public void setUsername(String username) {  
  38.         this.username = username;  
  39.     }  
  40.   
  41.     public String getPassword() {  
  42.         return password;  
  43.     }  
  44.   
  45.     public void setPassword(String password) {  
  46.         this.password = password;  
  47.     }  
  48.   
  49.     public List<File> getFile() {  
  50.         return file;  
  51.     }  
  52.   
  53.     public void setFile(List<File> file) {  
  54.         this.file = file;  
  55.     }  
  56.   
  57.     public List<String> getFileFileName() {  
  58.         return fileFileName;  
  59.     }  
  60.   
  61.     public void setFileFileName(List<String> fileFileName) {  
  62.         this.fileFileName = fileFileName;  
  63.     }  
  64.   
  65.     public List<String> getFileContentType() {  
  66.         return fileContentType;  
  67.     }  
  68.   
  69.     public void setFileContentType(List<String> fileContentType) {  
  70.         this.fileContentType = fileContentType;  
  71.     }  
  72.   
  73.     @Override  
  74.     public String execute() throws Exception {  
  75.         // 指定上传的位置  
  76.         String path = ServletActionContext.getRequest().getRealPath("/upload");  
  77.         for (int i = 0; i < file.size(); i++) {  
  78.             // 获取输入流  
  79.             InputStream is = new FileInputStream(file.get(i));  
  80.             byte[] buffer = new byte[1024];  
  81.             int length = 0;  
  82.             // 创建输出流对象  
  83.             OutputStream os = new FileOutputStream(new File(path, this  
  84.                     .getFileFileName().get(i)));  
  85.             // 开始上传  
  86.             while ((length = is.read(buffer)) > 0) {  
  87.                 os.write(buffer, 0, length);  
  88.             }  
  89.             // 一次关闭流  
  90.             os.close();  
  91.             is.close();  
  92.         }  
  93.         // 返回结果  
  94.         return SUCCESS;  
  95.     }  
  96. }  
 View : upload2.jsp
Java代码  收藏代码
  1. <%@ page language="java" import="java.util.*" pageEncoding="GB18030"%>  
  2. <%@ taglib prefix="s" uri="/struts-tags"%>  
  3.   
  4. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
  5. <html>  
  6. <head>  
  7. <title>My JSP 'upload2.jsp' starting page</title>  
  8. <meta http-equiv="pragma" content="no-cache">  
  9. <meta http-equiv="cache-control" content="no-cache">  
  10. <meta http-equiv="expires" content="0">  
  11. <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">  
  12. <meta http-equiv="description" content="This is my page">  
  13.   
  14. <script type="text/javascript">  
  15.                             function addMore() //触发此方法后添加一个,file元素  
  16.                             {  
  17.                             var td= document.getElementById("more");  
  18.   
  19.                             var br=document.createElement("br");  
  20.   
  21.                             var input = document.createElement("input");  
  22.   
  23.                             var button = document.createElement("input");  
  24.   
  25.                             input.type="file";  
  26.                             input.name="file";  
  27.   
  28.                             button.type="button";  
  29.                             button.value="Remove";  
  30.                             button.onclick=function ()//为Remove按钮注册一个点击事件  
  31.                             {  
  32.                                 td.removeChild(br);  
  33.                                 td.removeChild(input);  
  34.                                 td.removeChild(button);  
  35.                                 }  
  36.                             td.appendChild(br);  
  37.                             td.appendChild(input);  
  38.                             td.appendChild(button);  
  39.                                 }  
  40.                         </script>  
  41. </head>  
  42. <body style="text-align: center">  
  43.   
  44.     <div style="text-align: left">  
  45.         <s:fielderror cssStyle="color:red"></s:fielderror>  
  46.         <s:actionerror />  
  47.     </div>  
  48.     <s:form action="upload" method="post" enctype="multipart/form-data"  
  49.         theme="simple">  
  50.         <table border="1" width="80%">  
  51.             <tr>  
  52.                 <td>UserName:</td>  
  53.                 <td><s:textfield name="username"></s:textfield></td>  
  54.             </tr>  
  55.             <tr>  
  56.                 <td>PassWord:</td>  
  57.                 <td><s:password name="password"></s:password></td>  
  58.             </tr>  
  59.             <tr>  
  60.                 <td>File1:</td>  
  61.                 <td id="more"><s:file name="file"></s:file> <input  
  62.                     type="button" value="Add More" onclick="addMore()"></td>  
  63.             </tr>  
  64.             <tr>  
  65.                 <td><s:submit value="Submit"></s:submit></td>  
  66.                 <td></td>  
  67.             </tr>  
  68.   
  69.         </table>  
  70.     </s:form>  
  71. </body>  
  72. </html>  

  struts.xml的配置信息

Java代码  收藏代码
  1. <struts>  
  2.   
  3.     <constant name="struts.multipart.saveDir" value="e:\"></constant>//设置缓存文件的存放位置(当上传完成后,会被自动删除)  
  4.     <constant name="struts.i18n.encoding" value="gbk"></constant> //设置编码格式  
  5.     <constant name="struts.custom.i18n.resources" value="message"></constant>//当上传失败的时候,可以在指定的message.properties中定义显示的错误信息  
  6.   
  7.     <package name="struts2" extends="struts-default">  
  8.   
  9.         <action name="upload" class="org.viancent.action.UploadAction">  
  10.             <result name="success">/upload/result.jsp</result>  
  11.             <result name="input">/upload/upload2.jsp</result>  
  12.   
  13.             <interceptor-ref name="fileUpload">  
  14.                 <param name="allowedExtensions">.ppt,.txt</param>  
  15.                 <param name="maximumSize">409600</param>  
  16.             </interceptor-ref>  
  17.             <interceptor-ref name="defaultStack"></interceptor-ref>  
  18.         </action>  
  19.     </package>  
  20. </struts>  

 

Java代码  收藏代码
  1. //当上传的文件太大,或者文件类型不符合规定的时候我们可以自定义一个资源文件  
  2. //根据struts-message.properties中的默认属性名 在自己定义的资源文件中给这些属性重新赋值  
  3. struts.messages.error.file.too.large=File too large: {0"{1}" "{2}" {3}  
  4. //当文件太大的时候抛出的错误信息  
  5. struts.messages.error.content.type.not.allowed=Content-Type not allowed: {0"{1}" "{2}" {3}  
  6. //文件类型不符合规定的时候抛出的错误信息  
  7. struts.messages.error.file.extension.not.allowed=File extension not allowed: {0"{1}" "{2}" {3}  
  8. //当文件的扩展名不符合规定的时候抛出的错误信息  
  9. //注意这些错误都是FieldError级别的 如果希望在页面上显示,那么就要使用 <s:fielderror>标签  
  10.    

4.介绍一下关于defalut.properties 中的struts.multipart.maxSize 和 fileUpload中的

maximumSize的区别!

 

1.struts.multipart.maxSize掌控整个项目所上传文件的最大的Size。超过了这个size,后台报

错,程序处理不了如此大的文件。ActionError里面会有如下的提示:

the request was rejected because its size (16272982) exceeds the configured

maximum (9000000)

 

2.fileUpload拦截器的maximumSize属性必须小于struts.multipart.maxSize的值。

struts.multipart.maxSize默认2M,当maximumSize大于2M时,必须设置

struts.multipart.maxSize的值大于maximumSize。

 

3.当上传的文件大于struts.multipart.maxSize时,系统报错

当上传的文件在struts.multipart.maxSize和maximumSize之间时,系统提示:

File too large: file "MSF的

 

 

2.下载

a):关于下载主要是有struts-default.xml中的<result-type name="stream"

class="org.apache.struts2.dispatcher.StreamResult"/>来完成的

所以我们只需要设置struts.xml中对应下载的<action>中的<result type="">的type属性 将它设置成:

stream。

1.为stream对应的org.apache.struts2.dispatcher.StreamResult.class类的属性进行赋值主要有

如下属性:

 

Java代码  收藏代码
  1. //StreamResult类中的字段源码  
  2. /* 
  3.             protected String contentType = "text/plain";//设置下载文件的类型 
  4.             protected String contentLength;             //设置文件的大小 
  5.             protected String contentDisposition = "inline"; //设置下载的时候显示的文件名 
  6.             protected String contentCharSet ;               //设置编码格式 
  7.             protected String inputName = "inputStream";      
  8.             //设置对应下载的Action类中获取java.io.InputStream的类的名称 在Action中该类的名称最好为: 
  9.             // public InputStream getInputStream(){} 
  10.             protected int bufferSize = 1024;    //设置下载缓冲大小       
  11. */  

       2.具体实例如下:

struts.xml:

Java代码  收藏代码
  1. <action name="download" class="org.viancent.action.DownloadAction">  
  2.     <result name="success" type="stream">  
  3.           
  4.         <param name="contentType">application/vnd.ms-powerpoint</param>//这里的赋值方式 与 fileUploadInterceptor的allowedTypes方式相同  
  5.         <param name="contentDisposition">filename="${fileNames}"</param>  
  6.         /* 
  7.             ${fileNames} 这个el表达是是为了获取Action中 getFileNames()方法的返回值 
  8.             该方法是为了解决文件乱码实现的 
  9.         */  
  10.         <param name="inputName">inputStream</param>  
  11.         /* 
  12.             inputStream 是为了获取对应Action 中的getInputStream()方法的返回值 
  13.             该返回值的类型为 java.io.InputStream 
  14.         */  
  15.         <param name="bufferSize">4096</param>  
  16.           
  17.     </result>  
  18. </action>  

 Action:

Java代码  收藏代码
  1. package org.viancent.action;  
  2.   
  3. import java.io.InputStream;  
  4. import java.io.UnsupportedEncodingException;  
  5. import org.apache.struts2.ServletActionContext;  
  6. import com.opensymphony.xwork2.Action;  
  7. import com.opensymphony.xwork2.ActionContext;  
  8. import com.opensymphony.xwork2.ActionSupport;  
  9.   
  10. public class DownloadAction extends ActionSupport {  
  11.   
  12.     private String pathName; // 该字段是为了获取页面传过来的文件名称的信息  
  13.   
  14.     public String getPathName() {  
  15.         return pathName;  
  16.     }  
  17.   
  18.     public void setPathName(String pathName) {  
  19.         this.pathName = pathName;  
  20.     }  
  21.   
  22.     public String getFileNames() throws Exception {  
  23.         // 返回文件的名称 给<param  
  24.         // name="contentDisposition">filename="${fileNames}"</param>  
  25.         return this.getPathName();  
  26.     }  
  27.   
  28.     public InputStream getDownload() throws Exception {  
  29.         // 这里是一个重点 获取一个输入流  
  30.         return ServletActionContext.getServletContext().getResourceAsStream(  
  31.                 "/upload/"/* 获取WebRoot/upload/的某一个文件 */  
  32.                         + new String(this.getPathName().getBytes("iso-8859-1"),  
  33.                                 "gb18030"));  
  34.         // new String(this.getPathName().getBytes("iso-8859-1"),"gb18030")  
  35.         // 将文件名进行转码 转换成简体中文  
  36.         // 当没有找到该文件对象的时候 会抛出  
  37.         /* 
  38.          * Can not find a java.io.InputStream with the name [download] in the 
  39.          * invocation stack. Check the <param name="inputName"> tag specified 
  40.          * for this action. 
  41.          */  
  42.     }  
  43.   
  44.     @Override  
  45.     public String execute() throws Exception {  
  46.         return SUCCESS;  
  47.     }  
  48. }  

 Jsp (upload2.jsp)

<a href="/struts2/download.action?pathName=第四讲.ppt">下载一</a>
<a href="/struts2/download.action?pathName=12.txt">下载二</a>
/*
pathName=第四讲.ppt
对Action中的pathName属性进行赋值,用于指定下载哪一个文件
*/
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics