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"> <! -- 定义upload的Action,其实现类为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,代码如下所示。
<! -- 定义upload的Action,其实现类为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>