struts2文件上传下载

来源:互联网 发布:闪电网络 原理 编辑:程序博客网 时间:2024/06/09 07:38
struts2中也自带了文件上传与下载的功能
文件上传
         单文件上传
l     要想使用 HTML 表单上传一个或多个文件, 必须把 HTML 表单的 enctype 属性设置为 multipart/form-data, 把它的 method 属性设置为post
l  为了让用户能够选择一个文件进行上传, 程序员必须提供一个 <input type=“file”> 字段.
                   
<form action=""method="post" enctype="multipart/form-data">                            <input type="file" name="upload"/>                            <inputtype="submit" value="上传" />                   </form>


在 Struts 应用程序里, FileUpload 拦截器和 Jakarta Commons FileUpload 组件可以完成文件的上传.
<interceptorname="fileUpload"class="org.apache.struts2.interceptor.FileUploadInterceptor"/>
                   该拦截器位于defaultStack中,每个Action访问 都会执行
         步骤:
•    1. 在 Jsp 页面的文件上传表单里使用 file 标签. 如果需要一次上传多个文件, 就必须使用多个 file标签, 但它们的名字必须是相同的
•    2. 在 Action 中新添加 3 个和文件上传相关的属性. 这 3 个属性的名字必须是以下格式
•    uploadImage 是 jsp 页面上的 file 标签的名字.
          上传文件:<inputtype="file" name="uploadImage">
•    如果是上传单个文件, uploadImage属性的类型就是 java.io.File, 它代表被上传的文件, 第二个和第三个属性的类型是 String, 它们分别代表上传文件的文件名和文件类型
              定义方式是分别是jsp页面file组件的名称+ContentType,
                                           jsp页面file组件的名称+FileName
•    如果上上传多个文件, 可以使用数组或 List

例:public class UploadAction extends ActionSupport{        //在服务器端Action中定义对应成员变量,用于接收上传文件 和 相关数据      /*      * 例如 jsp中<input type="file" name="upload">      */      // 属性名要和 input元素name值一致      private File upload;      //jsp页面file组件的名称+ContentType,      private String uploadContentType;      //jsp页面file组件的名称+FileName      private String uploadFileName;      //为这三个成员变量生成set.get方法      public File getUpload() {          return upload;      }      public void setUpload(File upload) {          this.upload = upload;      }      public String getUploadContentType() {          return uploadContentType;      }      public void setUploadContentType(String uploadContentType) {          this.uploadContentType = uploadContentType;      }      public String getUploadFileName() {          return uploadFileName;      }      public void setUploadFileName(String uploadFileName) {          this.uploadFileName = uploadFileName;      }            @Override      public String execute() throws Exception {          //获得文件的真实路径创建文件,将接受的文件拷贝到这个文件中          String realPath = ServletActionContext.getServletContext().getRealPath("/source");          File file = new File(realPath,uploadFileName);          FileUtils.copyFile(upload, file);          return NONE;      }  }  struts.xml文件中的配置          <action name="upload" class="cn.itcast.action.UploadAction">              <interceptor-ref name="defaultStack">              设置文件最大的限制(拦截器fileUpload的maximumSize字段)                  <param name="fileUpload.maximumSize">20000000</param>              设置文件的要求的类型(拦截器fileUpload的allowedExtensions字段)                  <param name="fileUpload.allowedExtensions">.avi,.jpg</param>              </interceptor-ref>              出现错误后跳转的页面              <result name="input">/upload.jsp</result>          </action>  maximumSize与allowedExtensions在struts-default.xml文件中存在这样的一个拦截器,通过类名class可以找到类的源码,源码中就有这两个字段(不止两个,设置哪个用哪个)  <interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>  





l  FileUpload 拦截器负责处理文件的上传操作, 它是默认的 defaultStack拦截器栈的一员.
l  FileUpload 拦截器有 3 个属性可以设置.
•    maximumSize: 上传文件的最大长度(以字节为单位), 默认值为 2 MB
•    allowedTypes: 允许上传文件的类型, 各类型之间以逗号分隔
•    allowedExtensions: 允许上传文件扩展名, 各扩展名之间以逗号分隔
•    可以在struts.xml 文件中覆盖这 3 个属性
•   
•    若用户上传的文件大小大于给定的最大长度或其内容类型没有被列在 allowedTypes,allowedExtensions 参数里, 将会显示一条出错消息. 与文件上传有关的出错消息在
struts-messages.properties 文件里预定义了这些字段错误后给出的信息. (org.apache.struts2包下),可以在文件上传 Action相对应的资源文件中重新定义错误消息(国际化文件来覆盖原本的英文提示内容), 但需要在 struts.xml文件中配置使用。
注:在jsp中回显错误信息用 <s:fielderror/>显示错误信息
修改显示错误的资源文件的信息
第一步:创建新的资源文件 例如fileuploadmessage.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}
         备注:{0}:<inputtype=“file” name=“uploadImage”>中name属性的值
                     {1}:上传文件的真实名称
                     {2}:上传文件保存到临时目录的名称
                     {3}:上传文件的类型(对struts.messages.error.file.too.large是上传文件的大小)
 第二步:在struts.xml文件加载该资源文件
       <!-- 配置上传文件的出错信息的资源文件 -->
       <constantname="struts.custom.i18n.resources" value=“配置文件基名“/>
 
多文件上传
         客户端可以使用多个<inputfile> 同时进行文件上传
         如果 input filename 是不同的,则要配置多组文件、文件名、类型字段。

例:<input type="file" name="abc"/>      <input type="file" name="def"/>          class XxxAction {              private File abc;              private String abcContentType;              private String abcFileName;                            private File def;              private String defContentType;              private String defFileName;          }  如果 input file name相同  ---- 使用数组接收           <input type="file" name="upload"/>          <input type="file" name="upload"/>                    class XxxAction {              private File[] upload;              private String[] uploadContentType;              private String[] uploadFileName;          }    例:public class UploadMoreAction extends ActionSupport{      //字段为数组      private File[] upload;// 属性名要和 input元素name值一致      private String[] uploadContentType;      private String[] uploadFileName;      //提供set/get方法      public File[] getUpload() {          return upload;      }      public void setUpload(File[] upload) {          this.upload = upload;      }      public String[] getUploadContentType() {          return uploadContentType;      }      public void setUploadContentType(String[] uploadContentType) {          this.uploadContentType = uploadContentType;      }      public String[] getUploadFileName() {          return uploadFileName;      }      public void setUploadFileName(String[] uploadFileName) {          this.uploadFileName = uploadFileName;      }      @Override      public String execute() throws Exception {          //这里与单文件上传不同,要遍历文件名数组,对每一个上传文件进行上传          String realPath = ServletActionContext.getServletContext().getRealPath("/source");          for (int i = 0; i < uploadFileName.length; i++) {              File file = new File(realPath,uploadFileName[i]);              FileUtils.copyFile(upload[i], file);                      }          return NONE;      }  }  




文件下载
l  struts2提供了stream结果类型,该结果类型就是专门用于支持文件下载功能的
l  指定stream结果类型 需要指定一个 inputName参数,该参数指定一个输入流,提供被下载文件的入口
在struts-default.xml 文件中,结果集定义了一种stream类型
<result-typename="stream"class="org.apache.struts2.dispatcher.StreamResult"/>
HTTP响应 可以以一个流方式发送到客户端
注:请求中文文件名下载,get方式提交,需要手动编码 new String(filename.getBytes("ISO-8859-1"),"utf-8");
 
文件下载所必须的三点
         两个协议头信息ContentType(类型):文件类型
          ContentDisposition(下载附件名称):attachment;filename=文件名
         一个文件下载流
struts.xml文件中的配置

<action name="download" class="cn.itcast.action.demo2.DownloadAction">      <!-- 文件下载 使用流 结果集 -->          <result type="stream">          <!-- 文件MIME类型 -->          <!-- ${contentType} OGNL写法,用于读取Action中的getContentType方法,动态获取文件类型,下           载什么类型就是什么类型  -->          <param name="contentType">${contentType}</param>          <!-- 下载附件名称contentDisposition 格式为: attachment;filename=xxxx               ${filename}用于读取Action中的getFilename方法,动态获取文件名-->          <param name="contentDisposition">attachment;filename=${filename}</param>          <!-- 设置流方法名称,必须Action内部提供getTarget返回值InputStream ,用来返回文件内容  -->          <param name="inputName">target</param>      </result>  </action>    例:public class DownloadAction extends ActionSupport {      //文件名的成员变量,用于接受传递过来的文件名参数      private String filename;        public void setFilename(String filename) throws UnsupportedEncodingException {          //手动编解码,防止乱码          if(filename!=null){              this.filename = new String(filename.getBytes("ISO8859-1"),"utf-8");          }      }            @Override      public String execute() throws Exception {          // TODO Auto-generated method stub          return SUCCESS;      }            //提供getTarget放回InputStream流      public InputStream getTarget() throws FileNotFoundException{  String realPath = ServletActionContext.getServletContext().getRealPath("/source");          File downfile = new File(realPath,filename);          return new FileInputStream(downfile);      }            public String getConyentType(){          //通过ServletContext的getMimeType方法获取MIME类型  String mimeType = ServletActionContext.getServletContext().getMimeType(filename);          return mimeType;      }        public String getFilename() throws UnsupportedEncodingException {          //这里要判断用户的浏览器类型          String header = ServletActionContext.getRequest().getHeader("User-Agent");          //如果是火狐,那么在用户请求的头信息中的User-Agent就包含Firefox字段          if(header.contains("Firefox")){              //火狐要用BASE64编码格式:=?UTF-8?B?编码内容?=  return "?UTF-8?B?"+new BASE64Encoder().encode(filename.getBytes("utf-8"))+"?=";          }else {              //IE要用URL编码格式              return URLEncoder.encode(filename,"utf-8");          }      }  }  


  
jsp中(将要下载的文件名传过去)  
<a href="${pageContext.request.contextPath }/download.action?filename=壁纸.jpg">壁纸</a>  
<a href="${pageContext.request.contextPath }/download.action?filename=zzz.jpg">zzz</a>  
<a href="${pageContext.request.contextPath }/download.action?filename=abc.jpg">abc</a>  
1 0