zoukankan      html  css  js  c++  java
  • Struts2之文件上传下载

    本篇文章主要介绍如何利用struts2进行文件的上传及下载,同时给出我在编写同时所遇到的一些问题的解决方案。

    文件上传

    前端页面

     1 <!-- 引入struts标签 -->
     2 <%@taglib prefix="s" uri="/struts-tags"%>
     3 
     4 <!--
     5     使用struts中的<s:file></s:file>标签来选择文件。
     6     设置name属性,则提交后将传递后给后台一个name属性值(upload)的文件类型的文件。
     7     同时,将随同传递该文件的名字(uploadFileName)及文件类型(uploadContentType)
     8     表单中增加编码格式(enctype)为multipart/form-data
     9 -->
    10 <form action="upload" enctype="multipart/form-data" method="post">
    11     <s:file name="upload" label="Select File"/>
    12     <button type="submit">Submit</button>
    13 </form>
    home.jsp

    struts.xml

     1 <!-- 指定上传的文件暂时保存的位置 -->
     2 <constant name="struts.multipart.saveDir" value="/tmp"/>
     3 <package name="default" extends="struts-default">
     4     <!-- 上传文件action -->
     5     <action name="home">
     6         <result>/WEB-INF/content/home.jsp</result>
     7     </action>
     8     <action name="upload" class="com.wsy.action.UploadAction">
     9         <!-- 引入拦截器 -->
    10         <interceptor-ref name="fileUpload">
    11             <!-- 文件允许类型,可自行搜索查表,未指定则为默认所有类型 -->
    12             <param name="allowedTypes">image/jpeg,image/gif,text/plain</param>
    13             <!-- 文件最大大小 -->
    14             <param name="maximumSize">1024*1024</param>
    15         </interceptor-ref>
    16         <!-- 一定要引入defaultStack,否则将无法提交数据至后台 -->
    17         <interceptor-ref name="defaultStack"></interceptor-ref>
    18         <!-- 上传成功,返回首页 -->
    19         <result type="redirect">home.action</result>
    20         <!-- 上传不成功,设置input逻辑视图,进入报错页面 -->
    21         <result name="input">/WEB-INF/content/error.jsp</result>
    22     </action>
    23 </package>
    struts.xml

    文件上传action

     1 package com.wsy.action;
     2 
     3 import java.io.*;
     4 
     5 import org.apache.struts2.ServletActionContext;
     6 
     7 import com.opensymphony.xwork2.ActionSupport;
     8 
     9 public class UploadAction extends ActionSupport {
    10         private File upload;                // 上传的文件
    11         private String uploadContentType;    // 上传的文件的类型
    12         private String uploadFileName;        // 上传的文件的名字
    13         
    14         public File getUpload() {
    15             return upload;
    16         }
    17 
    18         public void setUpload(File upload) {
    19             this.upload = upload;
    20         }
    21 
    22         public String getUploadContentType() {
    23             return uploadContentType;
    24         }
    25 
    26         public void setUploadContentType(String uploadContentType) {
    27             this.uploadContentType = uploadContentType;
    28         }
    29 
    30         public String getUploadFileName() {
    31             return uploadFileName;
    32         }
    33 
    34         public void setUploadFileName(String uploadFileName) {
    35             this.uploadFileName = uploadFileName;
    36         }
    37 
    38         @Override
    39         public String execute() throws Exception
    40         {
    41             String path = ServletActionContext.getServletContext().getRealPath("/WEB-INF/uploadFiles");
    42             File file = new File(path);
    43 //            创建文件保存文件夹
    44             if (!file.exists())
    45                 file.mkdirs();
    46             FileOutputStream fos = new FileOutputStream(path + File.separator + getUploadFileName());
    47             FileInputStream fis = new FileInputStream(getUpload());
    48             byte[] buffer = new byte[1024];
    49             int len = 0;
    50             while ((len = fis.read(buffer)) > 0) {
    51                 fos.write(buffer , 0 , len);
    52             }
    53             fis.close();
    54             fos.close();
    55             return SUCCESS;
    56         }
    57 }
    UploadAction.java

    原理:Struts2文件上传通过将HTTP上传的数据先保存到临时文件夹(本文中为/tmp),然后使用fileUpload拦截器将文件绑定到Action的实例中,从而就能够以本地文件方式的操作浏览器上传的文件,将其保存到服务器下的特定位置。

    文件下载

    前端页面

     1 <ol>
     2     <% 
     3     String[] filelist = (String[])request.getSession().getAttribute("filelist");
     4     if (filelist != null) {
     5         for (int i = 0; i < filelist.length; i++) {
     6     %>
     7     <li><a href="download.action?filename=<%=filelist[i]%>"><%=filelist[i]%></a></li>
     8     <%
     9         }
    10     } else {
    11     %>
    12     <li>无文件</li>
    13     <% } %>
    14 </ol>
    home.jsp

    struts.xml

     1 <package name="download" extends="struts-default">
     2     <!-- 下载文件action -->
     3     <action name="download" class="com.wsy.action.DownloadAction">
     4         <result name="success" type="stream">
     5             <param name="contentType">image/jpeg,image/gif,text/plain</param>
     6             <!-- 获取输入流,根据值调用相应的get方法 -->
     7             <param name="inputName">targetFile</param>
     8             <!--
     9                 contentDisposition是文件下载的处理方式,包括内联(inline)和附件(attachment),默认是inline。
    10                 使用附件时这样配置:attachment;filename="文件名" 。
    11             -->
    12             <param name="contentDisposition">attachment;filename="${filename}"</param>
    13             <param name="bufferSizbe">1024*1024</param>
    14         </result>
    15     </action>
    16 </package>
    struts.xml

    文件下载action

     1 package com.wsy.action;
     2 
     3 import java.io.InputStream;
     4 
     5 import org.apache.struts2.ServletActionContext;
     6 import com.opensymphony.xwork2.ActionSupport;
     7 
     8 public class DownloadAction extends ActionSupport {
     9     private String filename;
    10     
    11     public String getFilename() {
    12         return filename;
    13     }
    14 
    15     public void setFilename(String filename) {
    16         this.filename = filename;
    17     }
    18 
    19     public InputStream getTargetFile() throws Exception {
    20         InputStream in = ServletActionContext.getServletContext().getResourceAsStream("/WEB-INF/uploadFiles/" + this.getFilename());
    21         return in;
    22     }
    23     
    24     public String execute() throws Exception {
    25         return SUCCESS;
    26     }
    27 }
    DownloadAction.java

    原理:同Servlet和HTTP协议时的文件下载。

    出现的问题

    1 上传文件时,

    严重: Exception occurred during processing request: /Users/apple/Documents/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/Union/WEB-INF/uploadFiles/acm.txt (No such file or directory)
    java.io.FileNotFoundException: /Users/apple/Documents/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/Union/WEB-INF/uploadFiles/acm.txt (No such file or directory)

    原因:设置放在uploadFiles文件夹下,但uploadFiles文件夹不存在,所以抛出文件不存在异常。

    解决方案:在上传文件的action创建文件输出流之前,先检测该文件夹是否存在,若不存在则创建。

    2 下载文件时,

    严重: Exception occurred during processing request: Can not find a java.io.InputStream with the name [targetFile] in the invocation stack. Check the <param name="inputName"> tag specified for this action.
    java.lang.IllegalArgumentException: Can not find a java.io.InputStream with the name [targetFile] in the invocation stack. Check the <param name="inputName"> tag specified for this action.

    原因:

    (1)struts.xml中返回中的inputName的值与action中的方法名不对应。

    (2)文件为不允许类型或超出文件设定大小。

    (3)action中创建文件输入流时传入的路径错误。

    (4)文件名中含有中文字符,则导致无法创建文件输入流。

    解决方案:

    针对(1)~(3),仔细检查。

    针对(4),在setFilename()方法返回时对文件名进行处理,

    1 public void setFilename(String filename) throws UnsupportedEncodingException {
    2     this.filename = new String(filename.getBytes("ISO8859-1"), "utf-8");
    3 }
    View Code

    而做了如上处理后,虽然没有异常被抛出,但发现在下载含中文字符的文件时,下载的文件的文件名仍然时乱码。

    所以就在Action中另添加一个方法。

    1 public String getDownloadFilename() throws UnsupportedEncodingException {
    2     return new String(filename.getBytes(), "ISO9959-1");
    3 }
    View Code

    并将struts.xml中result中的contentDisposition的值改为对象的值。

    1 <param name="contentDisposition">attachment;filename="${downloadFilename}"</param>
    View Code

    以上即为全部内容,欢迎提出问题和建议!

  • 相关阅读:
    约合¥1720 LG法国称G Watch将于6月开卖
    c语言中的位移位操作
    兼容的动态加载JS【原】
    Oracle 10g AND Oracle 11g手工建库案例--Oracle 10g
    面向对象思想----不看懊悔!
    学习设计模式--观察者模式(C++)
    使用POI 导入excel
    机器学习 F1-Score, recall, precision
    阿里无线11.11:手机淘宝移动端接入网关基础架构演进之路
    ICE 迁移64位安装问题
  • 原文地址:https://www.cnblogs.com/wsy06/p/5724429.html
Copyright © 2011-2022 走看看