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

7.3 文件上传高级配置

前面介绍了如何基于Struts 2完成文件上传,Struts 2还提供了文件上传的高级配置,从而实现文件保存目录的配置、文件过滤以及输出错误提示等。

7.3.1 配置文件保存目录

Struts 2提供了文件上传的高级配置,用来实现保存目录的配置。首先在Action中添加savePath属性,该属性用来封装上传文件保存目录,为该属性添加setter和getter方法,代码如下所示。

        public class UploadAction extends ActionSupport {
              // username属性用来封装用户名
              private String username;
              // myFile属性用来封装上传的文件
              private File myFile;
              // myFileContentType属性用来封装上传文件的类型
              private String myFileContentType;
              // myFileFileName属性用来封装上传文件的文件名
              private String myFileFileName;
              //savePath属性用来封装上传文件保存目录
              private String savePath;
              //获得上传文件保存目录
              public String getSavePath() {
                    return savePath;
              }
              //设置上传文件保存目录
              public void setSavePath(String savePath) {
                    this.savePath = savePath;
              }
            ...
            ...

在Action的execute()方法中修改设置文件目录代码,代码如下所示。

        // 设置上传文件目录
                    String uploadPath =  ServletActionContext.getServletContext().getRealPath(getSavePath());

在“struts.xml”文件中为该Action配置param元素,该元素用来为该Action中的savaPath属性动态分配属性值,代码如下所示。

        <! -- 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">
                          <param name="savePath">/upload02</param>
                          <! -- 定义处理结果与视图资源之间的关系-->
                          <result name="success">/result.jsp</result>
                          <result name="input">/upload.jsp</result>
                    </action>
              </package>
        </struts>

上传文件目录必须先创建好,如果在Web应用中没有创建该文件上传目录,那么将抛出异常,如图7.22所示。

7.3.2 实现文件过滤

Struts 2提供了文件上传的高级配置,用来实现文件的过滤。要实现文件过滤,只需配置文件上传拦截器的属性。文件上传拦截器中有如下两个属性。

        protected Long maximumSize;
        protected String allowedTypes;

图7.22 文件未找到抛出异常

❑ maximumSize:该属性用来指定上传文件大小的最大值,单位为字节(Byte)。

❑ allowedTypes:该属性用来指定允许上传的文件类型。

下面在“struts.xml”文件中配置该文件上传拦截器,指定上传文件大小的最大值为50KB,指定上传文件的类型为BMP或者JPG,代码如下所示。

        <! -- 定义uploadAction,其实现类为net.hncu.struts2.action.UploadAction-->
        <action name="upload"
              class="net.hncu.struts2.action.UploadAction">
              <param name="savePath">/upload02</param>
              <! -- 定义处理结果与视图资源之间的关系-->
              <result name="success">/result.jsp</result>
              <result name="input">/upload.jsp</result>
              <! -- 配置fileUpload拦截器 -->
              <interceptor-ref name="fileUpload">
                    <! -- 配置允许上传文件类型 -->
                    <param name="allowedTypes">image/bmp, image/pjpeg</param>
                    <! -- 配置允许上传文件大小最大值 -->
                    <param name="maximumSize">51200</param>
              </interceptor-ref>
              <interceptor-ref name="defaultStack"></interceptor-ref>
        </action>

文件大小倒是比较容易设置,但是文件类型的设置比较难。这时可以打开Tomcat安装目录下的conf文件夹,找到其中的“web.xml”文件,在该文件中列出了几乎所有的文件类型,代码如下所示。

        <mime-mapping>
            <extension>abs</extension>
              <mime-type>audio/x-mpeg</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>ai</extension>
              <mime-type>application/postscript</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>aif</extension>
              <mime-type>audio/x-aiff</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>aifc</extension>
              <mime-type>audio/x-aiff</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>aiff</extension>
              <mime-type>audio/x-aiff</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>aim</extension>
              <mime-type>application/x-aim</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>art</extension>
              <mime-type>image/x-jg</mime-type>
            </mime-mapping>
            <mime-mapping>
              <extension>asf</extension>
              <mime-type>video/x-ms-asf</mime-type>
            </mime-mapping>
            .....
            .....

7.3.3 输出错误提示

现在限制了文件上传的类型以及大小,那么如果用户提交不符合要求的文件,系统应该给出错误信息提示。很幸运,Struts 2的文件上传拦截器FileUploadInterceptor帮助做到了这一点。FileUpload-Interceptor拦截器将错误信息保存到fileldError中,FileUploadInterceptor拦截器代码如下所示。

        // If it' s null the upload failed
        if (file == null) {
                String errMsg = getTextMessage("struts.messages.error.uploading", new
        Object[]{inputName}, locale);
                  if (validation ! = null) {
                      validation.addFieldError(inputName, errMsg);
                }
                log.error(errMsg);
        } else if (maximumSize ! = null && maximumSize.longValue() < file.length()) {
                String errMsg = getTextMessage("struts.messages.error.file.too.large", new
          Object[]{inputName, file.getName(), "" + file.length()}, locale);
                  if (validation ! = null) {
                        validation.addFieldError(inputName, errMsg);
                  }
                  log.error(errMsg);
                } else if ((! allowedTypesSet.isEmpty()) && (! containsItem(allowedTypesSet, contentType))) {
                      String errMsg = getTextMessage("struts.messages.error.content.type.not.allowed", new
            Object[]{inputName, file.getName(), contentType}, locale);
                if (validation ! = null) {
                      validation.addFieldError(inputName, errMsg);
                }
                log.error(errMsg);
          } else {
              fileIsAcceptable = true;
          }

通过上面配置,如果文件上传失败,那么页面将跳转回“upload.jsp”用户输入页。因此只用在“upload.jsp”页面中添加输入错误信息代码,代码如下所示。

          <! -- 输出错误信息 -->
          <s:fielderror/>

这时如果上传不符合要求的文件,页面将提示错误信息。如提交一个不符合文件类型的GIF格式的图片,页面将提示Content-Type not allowed的错误信息,如图7.23所示。

图7.23 显示错误提示

显然这样的提示信息非常不友好,因此可以通过国际化信息来替换它。从拦截器FileUploadIntercepto类中可以得知上传文件太大的错误提示信息key为“struts. messages. error.file.too.large”,上传文件类型不允许的错误提示信息key为“struts.messages.error.content. type.not. allowed”。根据key信息新建国际化资源myMessage_zh_ CN.properties,代码如下所示。

          struts.messages.error.content.type.not.allowed = 文件类型不允许,请重新选择文件
          struts.messages.error.file.too.large              = 文件过大,请重新选择文件

通过native2ascii命令将字符转换成Unicode编码字符,代码如下所示。

          struts.messages.error.content.type.not.allowed=
          \u6587\u4EF6\u7C7B\u578B\u4E0D\u5141\u8BB8, \u8BF7\u91CD\u65B0\u9009\u62E9\u6587\u4EF6
          struts.messages.error.file.too.large=
            \u6587\u4EF6\u8FC7\u5927, \u8BF7\u91CD\u65B0\u9009\u62E9\u6587\u4EF6

在“struts.xml”中配置常量,用来加载该国际化资源文件,代码如下所示。

          <constant name="struts.custom.i18n.resources" value="myMessage"></constant>

这时如果上传不符合文件类型要求的文件,页面将提示错误信息“文件类型不允许,请重新选择文件”,如图7.24所示。这里还有一个问题需要特别注意,Struts 2默认配置了整个表单请求内容的最大字节数为2MB,代码如下。

        struts.multipart.maxSize=2097152

如果上传一个大于2MB文件,这时发现文件无法上传,但是页面并没有输出错误信息,而是在Tomcat服务器控制台中输出了错误提示信息,如图7.25所示。

图7.24 显示错误提示

图7.25 Tomcat服务器控制台输出错误提示信息

因为如果用户上传一个大于2MB文件,就看不到错误信息提示了。所以可以在“struts.xml”文件中配置该常量,改变其默认大小。这样就可以解决这类问题,代码如下。

        <constant name="struts.multipart.maxSize" value="20721520"></constant>