struts2--上传总结(限制大小和类型 非法上传的跳转)

时间:2023-03-10 06:48:06
struts2--上传总结(限制大小和类型 非法上传的跳转)

网上有很多版本,鉴于实践出真知的态度 我自己探索了一番

struts版本:2.3.16



限制大小:

struts2默认是2M 所以如果要扩大大小限制,应该先配一个全局struts2最大上限

<constant name="struts.multipart.maxSize" value="55000000"/><!-- 可上传50M的文件 -->

注意 100w大概是1M=1024*1024b≈100W

这样配置完后对于每个action我们都可以上传不超过50M的文件了

如果还要在单个action里面限制

这样配置:

<action name="upload" class="strutsFileUpload">
<result name="input" type="redirect">/admin/ChangePhoto.jsp</result>
<result name="userSuccess" type="redirect">/admin/index.jsp</result>
<interceptor-ref name="defaultStack">
<!-- 配置允许上传的文件大小,单位字节 10485760=10M-->
<param name="fileUpload.maximumSize">10485760</param>
</interceptor-ref> </action>

默认拦截器里面做配置(待会说原因):

<interceptor-ref name="defaultStack">
<param name="fileUpload.maximumSize">10485760</param> 

值得注意的是:如果 <constant .../> 里面配置的是50M 而action里面配置的是100M 那最后也只有50M

还有另外一种配置:但是只能限制大小不能限制类型:

<转>

使用Struts2上传文件,其实使用的是apache的 commons-fileupload-1.1.jar

在实际使用的过程中,使用如下配置fileUpload拦截器并不能过滤上传的文件类型,只能处理大小过滤。

<interceptor-ref name="defaultStack"/>
<!-- 限制文件上传大小和类型 -->
<interceptor-ref name="fileUpload">
<param name="maximumSize">10485760</param>
<param name="allowedTypes">
application/msword,application/pdf,application/zip
</param>
</interceptor-ref>

这样只能限制文件的大小,

如果不使用缺省的拦截器,则action中的属性不能正确赋值 就会出现jsp传到action里面的值不能得到 而为空。

而使用后,拦截类型不起作用。网上说缺省拦截器中已经包含了fileUpload拦截器。那么如上配置就是做了两次拦截。

那既然讲到限制类型,下面讲限制类型:

限制类型:

有两种配置:

1:

<action name="upload" class="strutsFileUpload">

            <result name="input" type="redirect">/admin/ChangePhoto.jsp</result>
<result name="userSuccess" type="redirect">/admin/index.jsp</result>
<interceptor-ref name="defaultStack">
<!-- 配置允许上传的文件类型,多个用","分隔 -->
<param name="fileUpload.allowedTypes">
image/png,image/gif,image/jpeg
</param>
</interceptor-ref> </action>

这样就能做到 限制了,只允许上面三种上传(PS:jpg也可以虽然上面有的只是jpeg但是我亲测是可以的,不放心可以再加一项)

2:

但是,用过这个参数的人都知道,allowedTypes是“文件类型”, 而不是“文件后缀名”,文件类型与文件后缀名有什么区别呢?

就如后缀名为bmp的图片的文件类型为image/bmp,后缀名为xls的Excel文件类型为application/vnd.ms-excel等等....

这各种各样的”文件类型“,让人烦不胜烦。。。。

猜想是否可以根据后缀名来过滤允许上次的文件,Struts如此红火的框架应该能想到这点。

于是便打开Struts文件上传的拦截器org.apache.struts2.interceptor.FileUploadInterceptor一看,发现如下代码:

protected Set<String> allowedTypesSet = Collections.emptySet();
protected Set<String> allowedExtensionsSet = Collections.emptySet();

看到一个allowedTypesSet和一个allowedExtensionsSet,很容易想到,前者是用于存放参数allowedTypes的,

而后者呢,自然是用于存放参数allowedExtensions的,extension翻为:延长、扩展...

所以,我们可以大胆的猜想,allowedExtensions参数就是用于配置”允许上传的文件后缀名“。

再来看看FileUploadInterceptor里的一个方法acceptFile(),此方法用于根据当前配置,检查该文件是否允许被上传

protected boolean acceptFile(Object action, File file, String filename, String contentType, String inputName, ValidationAware validation, Locale locale) {
boolean fileIsAcceptable = false; // If it's null the upload failed
if (file == null) {
String errMsg = getTextMessage(action, "struts.messages.error.uploading", new Object[]{inputName}, locale);
if (validation != null) {
validation.addFieldError(inputName, errMsg);
} LOG.warn(errMsg);
} else if (maximumSize != null && maximumSize < file.length()) {
String errMsg = getTextMessage(action, "struts.messages.error.file.too.large", new Object[]{inputName, filename, file.getName(), "" + file.length()}, locale);
if (validation != null) {
validation.addFieldError(inputName, errMsg);
} LOG.warn(errMsg);
} else if ((!allowedTypesSet.isEmpty()) && (!containsItem(allowedTypesSet, contentType))) {
String errMsg = getTextMessage(action, "struts.messages.error.content.type.not.allowed", new Object[]{inputName, filename, file.getName(), contentType}, locale);
if (validation != null) {
validation.addFieldError(inputName, errMsg);
} LOG.warn(errMsg);
} else if ((!allowedExtensionsSet.isEmpty()) && (!hasAllowedExtension(allowedExtensionsSet, filename))) {
String errMsg = getTextMessage(action, "struts.messages.error.file.extension.not.allowed", new Object[]{inputName, filename, file.getName(), contentType}, locale);
if (validation != null) {
validation.addFieldError(inputName, errMsg);
} LOG.warn(errMsg);
} else {
fileIsAcceptable = true;
} return fileIsAcceptable;
}

别的先不管,先看看到第2,3个else if节点,分别是利用了allowedTypesSet和allowedExtensionsSet,如下

} else if (allowedTypesSet不为空 && allowedTypesSet不包含该文件的类型) {  

// 添加错误信息....  

} else if (allowedExtensionsSet不为空 && allowedExtensionsSet不包含该文件的后缀名) {  

// 添加错误信息  

}  

从上面的代码中可以看出,如果我们要利用allowedExtensions参数来控制上传文件的后缀名,则不能配置allowedTypes参数。

否则,如果allowedTypes参数有配置,那么allowedExtensions参数将不会再起效。

总结

使用Struts文件上次功能,我们可以使用”文件类型“和”文件后缀名“两者中的一个来控制上传文件的类型/后缀名。但是,allowedTypes的优先级别高于allowedExtensions,如果配置了allowedTypes则allowedExtensions将不再起效。最后附上allowedExtensions的一个简单配置:

<action name="projectMake-Add" class="projectMake" method="add">
<result name="addsuccess" type="redirect">/admin/index2.jsp</result>
<result name="fileUploadFail" >/WEB-INF/infoFail.jsp</result>
<result name="input" >/WEB-INF/infoFail.jsp</result>
<interceptor-ref name="defaultStack">
<!-- 配置允许上传的文件类型,多个用","分隔 -->
<param name="fileUpload.allowedExtensions">
png,gif,jpeg
</param>
<!-- 配置允许上传的文件大小,单位字节 10485760=10M-->
<param name="fileUpload.maximumSize">10485760</param>
</interceptor-ref> </action>

当然 如果想用第一种的话,这边给出一些配置

'.a'      : 'application/octet-stream',
'.ai' : 'application/postscript',
'.aif' : 'audio/x-aiff',
'.aifc' : 'audio/x-aiff',
'.aiff' : 'audio/x-aiff',
'.au' : 'audio/basic',
'.avi' : 'video/x-msvideo',
'.bat' : 'text/plain',
'.bcpio' : 'application/x-bcpio',
'.bin' : 'application/octet-stream',
'.bmp' : 'image/x-ms-bmp',
'.c' : 'text/plain',
'.cdf' : 'application/x-cdf',
'.cdf' : 'application/x-netcdf',
'.cpio' : 'application/x-cpio',
'.csh' : 'application/x-csh',
'.css' : 'text/css',
'.dll' : 'application/octet-stream',
'.doc' : 'application/msword',
'.dot' : 'application/msword',
'.dvi' : 'application/x-dvi',
'.eml' : 'message/rfc822',
'.eps' : 'application/postscript',
'.etx' : 'text/x-setext',
'.exe' : 'application/octet-stream',
'.gif' : 'image/gif',
'.gtar' : 'application/x-gtar',
'.h' : 'text/plain',
'.hdf' : 'application/x-hdf',
'.htm' : 'text/html',
'.html' : 'text/html',
'.ief' : 'image/ief',
'.jpe' : 'image/jpeg',
'.jpeg' : 'image/jpeg',
'.jpg' : 'image/jpeg',
'.js' : 'application/x-javascript',
'.ksh' : 'text/plain',
'.latex' : 'application/x-latex',
'.m1v' : 'video/mpeg',
'.man' : 'application/x-troff-man',
'.me' : 'application/x-troff-me',
'.mht' : 'message/rfc822',
'.mhtml' : 'message/rfc822',
'.mif' : 'application/x-mif',
'.mov' : 'video/quicktime',
'.movie' : 'video/x-sgi-movie',
'.mp2' : 'audio/mpeg',
'.mp3' : 'audio/mpeg',
'.mpa' : 'video/mpeg',
'.mpe' : 'video/mpeg',
'.mpeg' : 'video/mpeg',
'.mpg' : 'video/mpeg',
'.ms' : 'application/x-troff-ms',
'.nc' : 'application/x-netcdf',
'.nws' : 'message/rfc822',
'.o' : 'application/octet-stream',
'.obj' : 'application/octet-stream',
'.oda' : 'application/oda',
'.p12' : 'application/x-pkcs12',
'.p7c' : 'application/pkcs7-mime',
'.pbm' : 'image/x-portable-bitmap',
'.pdf' : 'application/pdf',
'.pfx' : 'application/x-pkcs12',
'.pgm' : 'image/x-portable-graymap',
'.pl' : 'text/plain',
'.png' : 'image/png',
'.pnm' : 'image/x-portable-anymap',
'.pot' : 'application/vnd.ms-powerpoint',
'.ppa' : 'application/vnd.ms-powerpoint',
'.ppm' : 'image/x-portable-pixmap',
'.pps' : 'application/vnd.ms-powerpoint',
'.ppt' : 'application/vnd.ms-powerpoint',
'.ps' : 'application/postscript',
'.pwz' : 'application/vnd.ms-powerpoint',
'.py' : 'text/x-python',
'.pyc' : 'application/x-python-code',
'.pyo' : 'application/x-python-code',
'.qt' : 'video/quicktime',
'.ra' : 'audio/x-pn-realaudio',
'.ram' : 'application/x-pn-realaudio',
'.ras' : 'image/x-cmu-raster',
'.rdf' : 'application/xml',
'.rgb' : 'image/x-rgb',
'.roff' : 'application/x-troff',
'.rtx' : 'text/richtext',
'.sgm' : 'text/x-sgml',
'.sgml' : 'text/x-sgml',
'.sh' : 'application/x-sh',
'.shar' : 'application/x-shar',
'.snd' : 'audio/basic',
'.so' : 'application/octet-stream',
'.src' : 'application/x-wais-source',
'.sv4cpio': 'application/x-sv4cpio',
'.sv4crc' : 'application/x-sv4crc',
'.swf' : 'application/x-shockwave-flash',
'.t' : 'application/x-troff',
'.tar' : 'application/x-tar',
'.tcl' : 'application/x-tcl',
'.tex' : 'application/x-tex',
'.texi' : 'application/x-texinfo',
'.texinfo': 'application/x-texinfo',
'.tif' : 'image/tiff',
'.tiff' : 'image/tiff',
'.tr' : 'application/x-troff',
'.tsv' : 'text/tab-separated-values',
'.txt' : 'text/plain',
'.ustar' : 'application/x-ustar',
'.vcf' : 'text/x-vcard',
'.wav' : 'audio/x-wav',
'.wiz' : 'application/msword',
'.wsdl' : 'application/xml',
'.xbm' : 'image/x-xbitmap',
'.xlb' : 'application/vnd.ms-excel',
'.xls' : 'application/excel',
'.xls' : 'application/vnd.ms-excel',
'.xml' : 'text/xml',
'.xpdl' : 'application/xml',
'.xpm' : 'image/x-xpixmap',
'.xsl' : 'application/xml',
'.xwd' : 'image/x-xwindowdump',
'.zip' : 'application/zip',

常用的都有了 如果还有没找到的 请下面评论 或者自己类比推 或者谷歌^_^

那么限制都做好了;

非法上传的跳转:

如果文件上传过大,或者类型不对 系统会报错;

一个办法是:

<action>
<result name="input">/error/Error.jsp</result>
<interceptor-ref name="defaultStack">
<!-- 配置允许上传的文件类型,多个用","分隔 -->
<param name="fileUpload.allowedExtensions">
png,gif,jpeg
</param>
<!-- 配置允许上传的文件大小,单位字节 10485760=10M-->
<param name="fileUpload.maximumSize">10485760</param>
</interceptor-ref>
</action>

文件上传类型大小错误action会直接返回input,所以不需要在action中的方法出现一个 return "input" ;

当然 如果是这样的话,如果是前面有填写文章的内容,却因为上传的类型不对而跳转 不就白写了T_T,,,

所以用转发的方式 存了 content 然后转发的页面在<input value="<s:property  value="content"/>"/>即可

当然 最好的话就是js在上传的时候就判断给用户的感觉最好

版权声明:本文为博主原创文章,未经博主允许不得转载。