零基础学Struts
上QQ阅读APP看书,第一时间看更新

7.2 基于Struts 2完成文件上传

前面介绍了如何通过Common-FileUpload框架和COS框架来实现文件上传。Struts 2并没有提供上传组件,而是通过调用这些上传框架来实现的上传。Struts 2对于这些上传框架进行了进一步封装,从而更加简化了文件上传。

7.2.1 配置上传解析器

前面分别通过Common-FileUpload框架和COS框架实现了文件上传,下面来看如何基于Struts 2来完成文件上传。

前面提到过Struts 2并没有提供上传组件,而是通过调用这些上传框架来实现的上传,那么如何在Struts 2中配置这些上传框架呢?

首先打开导入“struts2-core-2.0.11.1.jar”库文件,找到org.apache.struts2包下的default.properties资源文件,代码如下所示。在该资源文件中给出了许多的Struts 2的默认配置,其中可以看到Struts 2默认使用jakarta作为其文件上传的解析器,代码如下所示。

        ### Parser to handle HTTP POST requests, encoded using the MIME-type multipart/form-data
        # struts.multipart.parser=cos
        # struts.multipart.parser=pell
        struts.multipart.parser=jakarta

其实jakarta是指Common-FileUpload框架。因为Common-FileUpload项目属于jakarta的子项目。如果在Struts 2项目中使用Common-FileUpload框架来上传文件,只需将“commons-fileupload-1.2.1.jar”库文件以及“commons-io-1.4.jar”库文件复制到Web应用中的WEB-INF下的lib目录中。

如果希望使用COS框架来上传文件,只需“cos.jar”库文件复制到Web应用中的WEB-INF下的lib目录中,然后修改struts.multipart.parser常量值。常量值修改分两种方法,一种是在struts.properties中修改,另一种是在“struts.xml”文件中修改。

❑ 在struts.properties中修改,指定struts.multipart.parser常量值为cos,代码如下。

        struts.multipart.parser=cos

❑ 在struts.xml文件中修改,指定struts.multipart.parser常量值为cos,代码如下。

        <constant name="struts.multipart.parser" value="cos"></constant>

在Struts 2中使用这两种上传框架没有什么不同,Struts 2已经在这两个上传框架之上再封装了一层,这种封装完全取消了两种框架上传时的区别。

这时如果需要替换上传框架,只需修改struts.multipart.parser常量值,指定使用的上传框架即可。

7.2.2 实现文件上传Action

下面来看如何基于Struts 2完成单个文件上传。首先创建用户输入页,该页面仅仅包含一个表单,用来输入用户名以及选择用来上传的文件,表单提交到upload.action,代码如下所示。

        <%@ page language="java" pageEncoding="gb2312"%>
        <html>
          <head>
            <title>文件上传</title>
          </head>
            <center>
            <h1>Struts 2完成上传</h1>
              <form action="upload.action" method="post" enctype="multipart/form-data">
                  <table>
                      <tr>
                            <td>用户名:</td>
                            <td><input type="text" name="username" ></td>
                      </tr>
                      <tr>
                            <td>上传文件:</td>
                            <td><input type="file" name="myFile"></td>
                      </tr>
                      <tr>
                            <td><input type="submit" value="上传"></td>
                            <td><input type="reset"></td>
                      </tr>
                    </table>
              </form>
          </center>
          <body>
          </body>
        </html>

Struts 2的文件上传是通过文件上传拦截器来完成的。在“struts-default.xml”配置文件中找到文件上传拦截器的配置,代码如下所示。

        <interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>

在org.apache.struts2.interceptor包中找到文件上传拦截器FileUploadInterceptor。打开FileUploadInterceptor类,首先来看这样一段注释。

        * <ul>
          *
          * <li>[File Name] : File - the actual File</li>
          *
          * <li>[File Name]ContentType : String - the content type of the file</li>
          *
         * <li>[File Name]FileName : String - the actual name of the file uploaded (not the HTML name)</li>
          *
          * </ul>

这段注释用来说明如何在Action中配置其属性。其中File Name属性类型为File,表示用户上传的文件。[File Name]ContentType属性封装上传文件的类型,[File Name]FileName属性封装上传文件的文件名。这里的Fiel Name就是指用户提交表单中的文件域的name属性。

在Action中属性一般都是与提交的参数相对应的,这里并没有提交FileNameContentType和File NameFileName参数。这就要归功于FileUploadInterceptor文件上传拦截器了,查看FileUploadInterceptor类中的这段代码。

        if (acceptFile(files[index], contentType[index], inputName, validation, ac.getLocale())) {
                                                parameters.put(inputName, files);
                                                parameters.put(inputName + "ContentType", contentType);
                                                parameters.put(inputName + "FileName", fileName);
                                            }

通过FileUploadInterceptor拦截器添加相应的参数。拦截器已经做了很多的工作,所以使得开发变得非常简单。下面来完成文件上传Action,代码如下所示。

        package net.hncu.struts2.action;
        import java.io.File;
        import java.io.FileInputStream;
        import java.io.FileOutputStream;
        import java.io.InputStream;
        import java.io.OutputStream;
        import org.apache.struts2.ServletActionContext;
        import com.opensymphony.xwork2.ActionSupport;
        public class UploadAction extends ActionSupport {
              // username属性用来封装用户名
              private String username;
              // myFile属性用来封装上传的文件
              private File myFile;
              // myFileContentType属性用来封装上传文件的类型
              private String myFileContentType;
              // myFileFileName属性用来封装上传文件的文件名
              private String myFileFileName;
              //获得username
              public String getUsername() {
          return username;
    }
    //设置username
    public void setUsername(String username) {
          this.username = username;
    }
    //获得myFile
    public File getMyFile() {
          return myFile;
    }
    //设置myFile
    public void setMyFile(File myFile) {
          this.myFile = myFile;
    }
    //获得myFileContentType
    public String getMyFileContentType() {
          return myFileContentType;
    }
    //设置myFileContentType
    public void setMyFileContentType(String myFileContentType) {
          this.myFileContentType = myFileContentType;
    }
    //获得myFileFileName
    public String getMyFileFileName() {
          return myFileFileName;
    }
    //设置myFileFileName
    public void setMyFileFileName(String myFileFileName) {
          this.myFileFileName = myFileFileName;
    }
    public String execute() throws Exception {
          //基于myFile创建一个文件输入流
          InputStream is = new FileInputStream(myFile);
          // 设置上传文件目录
          String uploadPath = ServletActionContext.getServletContext()
                      .getRealPath("/upload");
          // 设置目标文件
          File toFile = new File(uploadPath, this.getMyFileFileName());
          // 创建一个输出流
          OutputStream os = new FileOutputStream(toFile);
          //设置缓存
          byte[] buffer = new byte[1024];
          int length = 0;
          //读取myFile文件输出到toFile文件中
          while ((length = is.read(buffer)) > 0) {
                              os.write(buffer, 0, length);
                      }
                      //关闭输入流
                      is.close();
                      //关闭输出流
                      os.close();
                      return SUCCESS;
                }
          }

7.2.3 配置文件上传Action

在“struts.xml”文件中配置文件上传Action。定义upload的Action,指定其实现类为net.hncu. struts2.action.UploadAction。为了使其能够接受中文参数值,设置参数编码为gb2312,代码如下所示。

        <? xml version="1.0" encoding="UTF-8" ? >
        <! DOCTYPE struts PUBLIC
            "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
            "http://struts.apache.org/dtds/struts-2.0.dtd">
        <! -- struts为配置文件根元素-->
        <struts>
              <! -- 设置参数编码 -->
              <constant name="struts.i18n.encoding" value="gb2312"></constant>
              <! -- Action必须放在指定的包名空间中-->
              <package name="struts2" extends="struts-default">
                    <! -- 定义uploadAction,其实现类为net.hncu.struts2.action.UploadAction-->
                    <action name="upload"
                        class="net.hncu.struts2.action.UploadAction">
                        <! -- 定义处理结果与视图资源之间的关系-->
                        <result name="success">/result.jsp</result>
                        <result name="input">/upload.jsp</result>
                    </action>
              </package>
        </struts>

7.2.4 测试文件上传

打开用户输入页,填写用户名并选择文件进行上传,如图7.19所示。

页面跳转到结果输出页。页面中显示了用户名以及上传的文件名,如图7.20所示。

下面打开文件上传目录upload,在该目录中可以看到刚才上传的文件,如图7.21所示。

现在基于Struts 2完成了文件上传,但是还有以下问题没有解决。

❑ 文件保存目录问题:在Action中配置文件目录,修改起来比较麻烦。

❑ 文件大小以及类型问题:上传文件大小以及类型没有限制。

❑ 错误提示问题:如果上传不符合配置的文件应该提示其错误信息。

图7.19 用户输入页

图7.20 结果输出页

图7.21 上传目录upload