4.4.1 Struts2文件上传功能开发
技术要点
本节代码详细说明文件上传功能的开发流程,介绍知识点如下:
 
=   文件上传页面和显示上传成功页面代码内容。
 
=   UploadAction类中实现上传功能方法和上传文件属性介绍。
 
=   struts.xml中UploadAction配置,以及字符编码、文件临时存放路径配置。
 
=   上传后所处路径和最终上传成功后效果展示。
 
演示代码
上传文件页面,这里笔者定义的是多个文件上传。
 

<!-------------------------------------------文件名:upload.jsp-------------------------------->

  

 <%@taglibprefix="s" uri="/struts-tags"%>

  

 <html>

  

 <head>

  

         <metahttp-equiv="Content-Type" content="text/html;charset=gb2312">

  

         <title>上传文件</title>

  

 </head>

  

 <body>

  

 <!-- 上传文件表单定义 -->

  

 <s:formaction="upload" method="post"enctype="multipart/form-data">

  

         <tr>

  

 <!-- 上传文件标签定义 -->

  

 <td>上传文件:<s:filename="file"></s:file></td>

  

 </tr>

  

 <tr>

  

 <td>再次上传文件:<s:filename="file"></s:file></td>

  

 </tr>

  

 <tr>

  

 <tdalign="left"><s:submit name="submit" value="提交"></s:submit></td>

  

 </tr>

  

 </s:form>

  

 </body>

  

 </html>

  

 上传文件成功后结果页面

  

 <!-------------------------------------------文件名:result.jsp -------------------------------->

  

 <%@taglibprefix="s" uri="/struts-tags"%>

  

 <html>

  

 <head>

  

         <metahttp-equiv="Content-Type" content="text/html;charset=gb2312">

  

         <title>上传结果</title>

  

 </head>

  

 <body>

  

         上传文件:

  

         <!-- 显示上传成功文件名 -->

  

         <s:propertyvalue="fileFileName" />

  

 </body>

  

 </html>

  

 UploadAction类代码

  

 <!-------------------------------------------文件名:UploadAction.java -------------------------------->

  

 import java.io.File;

  

 importjava.io.FileInputStream;

  

 importjava.io.FileNotFoundException;

  

 importjava.io.FileOutputStream;

  

 importjava.io.IOException;

  

 importjava.io.InputStream;

  

 importjava.io.OutputStream;

  

 import java.util.List;

  

   

  

 importorg.apache.struts2.ServletActionContext;

  

 importcom.opensymphony.xwork2.ActionSupport;

  

   

  

 //文件上传Action

  

 public class UploadAction extends ActionSupport {

  

 //上传文件存放路径

  

 private final static StringUPLOADDIR = "/upload";

  

 //上传文件集合

  

 private List<File> file;

  

 //上传文件名集合

  

 private List<String>fileFileName;

  

 //上传文件内容类型集合

  

 private List<String>fileContentType;

  

   

  

 public List<File> getFile() {

  

         return file;

  

 }

  

   

  

 public void setFile(List<File> file) {

  

         this.file = file;

  

 }

  

   

  

 public List<String>getFileFileName() {

  

         return fileFileName;

  

 }

  

   

  

 public void setFileFileName(List<String> fileFileName) {

  

         this.fileFileName = fileFileName;

  

 }

  

   

  

 public List<String>getFileContentType() {

  

         return fileContentType;

  

 }

  

   

  

 public void setFileContentType(List<String> fileContentType) {

  

         this.fileContentType =fileContentType;

  

 }

  

   

  

 public String execute() throws Exception {

  

         for (int i = 0; i < file.size(); i++) {

  

                //循环上传每个文件

  

                uploadFile(i);

  

         }

  

         return "success";

  

 }

  

   

  

 //执行上传功能

  

 private void uploadFile(inti) throws FileNotFoundException,IOException {

  

         try {

  

                InputStreamin = newFileInputStream(file.get(i));

  

                Stringdir = ServletActionContext.getRequest().getRealPath(UPLOADDIR);

  

                FileuploadFile = new File(dir, this.getFileFileName().get(i));

  

                OutputStreamout = newFileOutputStream(uploadFile);

  

                byte[] buffer = new byte[1024 * 1024];

  

                int length;

  

                while ((length = in.read(buffer)) >0) {

  

                       out.write(buffer,0, length);

  

                }

  

   

  

                in.close();

  

                out.close();

  

         } catch (FileNotFoundException ex) {

  

                ex.printStackTrace();

  

         } catch (IOException ex) {

  

                ex.printStackTrace();

  

         }

  

 }

  

 }

  

 struts.xml配置文件中有关文件上传的配置:

  

 <!-------------------------------------------文件名:struts.xml-------------------------------->

  

 <struts>

  

 <!-- 系统常量定义,定义上传文件字符集编码 -->

  

 <constantname="struts.i18n.encoding"value="gb2312"></constant>

  

 <!-- 系统常量定义,定义上传文件临时存放路径 -->

  

 <constantname="struts.multipart.saveDir"value="c:\"></constant>

  

 <!-- Action所在包定义 -->

  

 <packagename="C04.4" extends="struts-default">

  

         <!--Action名字,类以及导航页面定义 -->

  

         <!-- 通过Action类处理才导航的的Action定义 -->

  

         <actionname="upload" class="action.UploadAction">

  

                <resultname="input">/jsp/upload.jsp</result>

  

                <resultname="success">/jsp/result.jsp</result>

  

         </action>

  

 </package>

  

 </struts> 

  

 (1):文件上传页面如图4.8所示。

  

 图4.8  文件上传

  

 (2):选择文件如图4.9所示。

  

 图4.9  选择上传的文件

  

 (3):单击“提交”按钮后文件上传成功页面,并显示上传文件名,如图4.10所示。

  

 图4.10 上传文件成功后效果

  

   

  

 上传的文件的位置:此项目用的服务器是Tomcat,在Tomcat中的webapps中此项目中的根目录下。自己找找看吧,下载时也即将从这里下载文件的。

  

 明天继续学习下载文件。^_^

  

   

  

   

  

   

  

   

  

   

  

   

  

 Struts2文件下载功能开发

 技术要点

 本节代码详细说明文件下载功能的开发流程,介绍知识点如下:

  

 =   上传成功页面重修改后支持文件下载代码内容。

  

 =   DownloadAction文件下载功能开发。

  

 =   struts.xml中DownloadAction配置,以及支持文件名为中文字符的文件下载。

  

 =   下载文件流程展示。

  

 演示代码

 上传成功页面,这里笔者让其在每个上传文件后提供“下载”链接。

  

 <!-------------------------------------------文件名:result.jsp-------------------------------->

  

 <%@taglibprefix="s" uri="/struts-tags"%>

  

 <body>

  

         上传文件:

  

         <table>

  

         <!--循环显示上传成功文件名 -->

  

         <s:iteratorvalue="fileFileName" status="fn">

  

         <tr>

  

         <td>

  

         <!--上传成功文件名 -->

  

         <s:property/>        

  

         </td>

  

         <td>

  

         <!--下载文件链接内容为定义的下载Action -->

  

         <!--下载文件名作为链接参数fileName值,用OGNL表达式表达 -->       

  

         <ahref="<s:url value='download.action'>                        

  

                     <s:param name='fileName'

  

  value='fileFileName[#fn.getIndex()]'/>  

  

                 </s:url>">下载</a>

  

         </td>

  

         </tr>

  

         </s:iterator>          

  

         </table>         

  

 </body>

  

 DownLoadAction类代码

  

 <!-------------------------------------------文件名:DownLoadAction.java -------------------------------->

  

 import java.io.InputStream;

  

 import java.io.UnsupportedEncodingException;

  

   

  

 import org.apache.struts2.ServletActionContext;

  

 import com.opensymphony.xwork2.ActionSupport;

  

   

  

 public classDownLoadAction extendsActionSupport {

  

 //下载文件原始存放路径

  

 private final static String DOWNLOADFILEPATH="/upload/";

  

 //文件名参数变量

  

 private StringfileName;

  

   

  

 public StringgetFileName() {

  

            returnfileName;

  

 }

  

   

  

 public void setFileName(String fileName) {

  

            this.fileName= fileName;

  

 }

  

   

  

 //从下载文件原始存放路径读取得到文件输出流

  

 public InputStreamgetDownloadFile() {

  

            return

  

 ServletActionContext.getServletContext().getResourceAsStream(DOWNLOADFILEPATH+fileName);

  

 }

  

 //如果下载文件名为中文,进行字符编码转换

  

 public StringgetDownloadChineseFileName() {

  

            String downloadChineseFileName = fileName;

  

   

  

            try {

  

                     downloadChineseFileName = new String(downloadChineseFileName.getBytes(),"ISO8859-1");

  

            } catch(UnsupportedEncodingException e) {

  

                     e.printStackTrace();

  

            }

  

   

  

            returndownloadChineseFileName;

  

 }

  

   

  

 public Stringexecute() {

  

            return SUCCESS;

  

 }

  

 }

  

 struts.xml配置文件中有关文件下载的配置:

  

 <!-------------------------------------------文件名:struts.xml-------------------------------->

  

 <struts>

  

 <!-- 下载文件的Action定义 -->

  

            <action name="download"class="action.DownLoadAction">

  

                     <!-- 设置文件名参数,由页面上传入 -->

  

                     <param name="fileName"></param>

  

                     <result name="success"type="stream">

  

                              <!-- 下载文件类型定义 -->

  

                              <paramname="contentType">text/plain</param>

  

                              <!-- 下载文件处理方法 -->

  

                              <paramname="contentDisposition">

  

                                        attachment;filename="${downloadChineseFileName}"

  

                              </param>

  

                              <!-- 下载文件输出流定义 -->

  

                              <paramname="inputName">downloadFile</param>

  

                     </result>

  

            </action>

  

 </struts>


 
(1):文件开始下载页面如图4.12所示。
 
图4.12  文件下载
 
(2):单击“下载”链接,比如点“下载文件1.txt”文件右边“下载”链接,出现对话框如图4.13所示。
 
图4.13  下载文件处理方式
 
(3):单击“保存”按钮后选择下载文件存放路径,如图4.14所示。
 
图4.14  下载文件选择存放路径
 
代码解释
(1)在result.jsp中通过iterator标签和url标签定义了“fileFileName”的循环显示以及链接。其中有关“status”和OGNL表达式笔者会在之后章节里具体介绍,这里只是让读者知道是如何使用标签显示图4.12显示的内容。特别指出<param>标签为downloadAction定义了一个参数,该参数名为“fileName”,因为在4.4.1小节中笔者定义的“fileFileName”是个List类型的数据集合,因此利用OGNL表达式将文件名作为“fileName”参数值传入downloadAction中。
 
(2)DownLoadAction文件中先定义了常量DOWNLOADFILEPATH,它是下载文件在服务器存放的路径名,也就是4.4.1小节中上传文件在服务器存放的路径名。
 
定义好DOWNLOADFILEPATH后,在定义DownLoadAction的属性变量。因为在result.jsp中定义了参数“fileName”,则它作为DownLoadAction的属性变量,需要定义相应的getter、setter方法。
 
然后定义了getDownloadFile方法,它返回的是一个文件流,表明将被下载文件转换为输出流,方便下载。利用Struts2自带的“ServletActionContext”类的API把下载文件存放路径作为方法参数,读取下载文件,将其转换为文件流。
 
还有一个getDownloadChineseFileName方法,该方法主要作用是将文件名为中文字符的文件进行文件名的字符编码集合转换。因为在Web系统中由JSP等视图页面传入的变量值,特别是中文字符的变量。缺省的字符编码集合都是“ISO8859-1”,因此利用Java的字符串类的API,将字符编码转成开发需要的字符编码集。防止中文字符乱码问题发生。
 
(3)struts.xml中定义了名为“download”的Action。其中它自己的参数“fileName”因为在这里它的值会从JSP页面上传入,所以这里只是定义,没有具体给它赋任何值
 
在<result>标签中定义了type属性,值为“stream”。如果是下载文件功能开发,DownLoadAction一定要设置type属性,而且值为“stream”。这是因为在Struts2自带的xml配置文件为struts-default.xml中有关于“stream”的result返回类型的定义,代码如下:
 
<!-------------------------------------------文件名:struts-default.xml-------------------------------->
 
<result-typename="stream"class="org.apache.struts2.dispatcher.StreamResult"/>
 
这里Struts2定义了result返回类型为“stream”,这个result类型主要是处理文件的输入和输出流时候需要使用的。因为下载文件就是把文件转换成输入输出流,将其从一个文件路径放到另外一个文件路径中去。所以肯定要设置这个result类型的。
 
“contentType”、“contentDisposition”、“inputName”都是这个result的属性。“contentType”就是文件类型。这里因为下载的文件是文本文件,因此设定的值为文本文件类型,具体各个文件类型如何定义,4.4.1小节已经介绍过,这里不再做说明。“contentDisposition”是指定下载文件处理方式,如图4.13就是处理方式的效果。特别指出如果“contentDisposition”定义的值把前面的“attachment”去掉,则下载方式不是以附件方式下载,如果单击“下载”链接,则会把下载文件的内容显示在浏览器中。读者可以去试验一下。这里有个“${downloadChineseFileName}”,这就是在DownLoadAction中定义getDownloadChineseFileName方法的目的,${downloadChineseFileName}是OGNL的表达式,它显示了“downloadChineseFileName”变量的具体值,因为在DownLoadAction中定义getDownloadChineseFileName方法,则把已经转换成符合需要字符编码集的下载文件名作为下载文件方式对话框中显示的名称,不会造成任何乱码问题。“inputName”是最关键的一个属性,也是一定要定义的属性,“inputName”参数中定义的值“downloadFile”就是DownLoadAction中getDownloadFile方法返回的文件流名字。在Struts2中Acion用前缀名为get的方法得到各种属性的值,这些属性有些是在Action中定义,有些就像本示例在配置文件中利用OGNL表达式或直接定义。
 
(4)开始进行文件下载功能展示,按照如上记述的步骤执行即可。笔者将两个文本文件上传上去,然后在上传成功页面对具体的文件进行下载。在图4.13中单击“保存”按钮就显示图4.14,选择在本机上存放下载文件的路径即可完成下载文件