当Apache Shiro遇上MultipartHttpServletRequest

####项目是SpringMVC框架,配置了SpringMVC文件上传,同时使用了Apache Shiro。 ####可以确定配置是无误的,表单也有enctype="multipart/form-data"属性。 ####如下代码,当用MultipartHttpServletRequest接收文件上传请求时

@RequestMapping(value = "addOrUpdate", method = RequestMethod.POST)
public String addOrUpdate(MultipartHttpServletRequest request) {
    // 业务逻辑
}

####会报告如下错误

Current request is not of type [org.springframework.web.multipart.MultipartHttpServletRequest]: org.apache.shiro.web.servlet.ShiroHttpServletRequest@9a1d0ff

####暂时的解决方案如下

public String addOrUpdate(MultipartHttpServletRequest request) {
    MultipartResolver resolver = new CommonsMultipartResolver(request.getSession().getServletContext());
    MultipartHttpServletRequest multipartRequest = resolver.resolveMultipart(request);
List<String> uploadPaths = fileUpload(multipartRequest);

####fileUpload方法如下

private List<String> fileUpload(MultipartHttpServletRequest multipartRequest) {
		List<String> uploadPaths = new ArrayList<String>();
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
		Set<String> keys = fileMap.keySet();
		for(String key : keys){
			CommonsMultipartFile item = (CommonsMultipartFile)fileMap.get(key);
			if (!item.isEmpty()) {
				String fileName = item.getOriginalFilename();// 获得文件的完整路径
				// 判断是否有图片上传
				if (!("".equals(fileName)) && !(fileName == null)) {
					String menulogoPath = Global.getConfig("upload.logo.menu");
					File dir = new File(menulogoPath);
					// 更改文件的保存路径,以防止文件重名的现象出现
					if (!dir.exists()) {
						dir.mkdirs();
					}

					String datetime = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
					String filenewName = datetime + "-" + fileName;
					File uploadedFile = new File(dir, filenewName);

					try {
						// 如果在该文件夹中已经有相同的文件,那么将其删除之后再重新创建(只适用于上传一张照片的情况)
						if (uploadedFile.exists()) {
							uploadedFile.delete();
						}
						item.getFileItem().write(uploadedFile);
						uploadPaths.add(filenewName);
						System.out.println("return : " + filenewName);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}
		return uploadPaths;
	}

####项目是比较陈旧的项目了,不确定错误原因是否是Shiro过滤文件上传引起的,不知道是否还有更好的解决方案(如通过某些配置可以解决问题),以后研究了此问题再来更新。

###===========================更新=========================== ###===========================我是分割线===========================

###经过调试发现Apache Shiro和 SpringMVC MultipartHttpServletRequest是没有任何冲突的。 ###之所以报告上面的错误是因为我忘记配置multipartResolver导致

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">  
        <property name="maxUploadSize" value="10485760"/>
        <property name="maxInMemorySize" value="4096"/>
        <property name="defaultEncoding" value="UTF-8"/>
	    <property name="resolveLazily" value="true"/>  
	</bean>

###===========================再分割=========================== ####问题虽然得到解决,但在调试过程中却发现了另一个问题,予以记录。 ####通常,我们使用SpringMVC的时候,JSP页面的表单只要写上对应实体类的属性,在Controller层,SpringMVC是会自动为我们将属性封装成实体的 ####但当我们牵涉到文件上传的时候,则有可能遭遇一个小陷阱。 ####例如,我们有实体类_Product.java_如下

public class Product {
    private String name; // 商品名称
    private String imgURL; // 商品图片
    // getter setter 省略
}

####对应的添加页面如下

<form action="" method="post" enctype="multipart/form-data">
    <input name="name" type="text" value="" >
    <input name="imgURL" type="file" />
    <input value="提交"  type="submit">
</form>

####Controller层如下

@RequestMapping("")
public String addProduct(Product p, MultipartFile imgURL) throws Exception {
    // 业务逻辑
    return "";
}

####理论上你是不是在期待SpringMVC帮你把相关属性封装进Product,imgURL用于接收页面上对应的文件。 ####遗憾的是你只会遇到_HTTP 400_错误,控制台也没有报告任何错误! ####造成错误的原因是SpringMVC帮你把相关属性封装进Product的时候,文件类型是无法用String接收的。 ####所以你也该知道怎么解决了... ###===========================补充===========================

public String addOrUpdate(HttpServletRequest request) throws Exception {
    MultipartResolver resolver = new CommonsMultipartResolver(request.getSession().getServletContext());
    MultipartHttpServletRequest multipartRequest = resolver.resolveMultipart(request);
    Map<String,MultipartFile> fileMap = multipartRequest.getFileMap();
    MultipartFile imageUrlFile = fileMap.get("imageUrlFile");
    MultipartFile imageUrlHoverFile = fileMap.get("imageUrlHoverFile");
    // 从multipartRequest得到MultipartFile的简单方式,spFiles是页面file的名称
    //  List<MultipartFile> list = multipartRequest.getFiles("spFiles")
}

###===========================20160606补充=========================== ####同理,当你用来接收页面数据的实体类包含Date类型,SpringMVC默认是没有相应转换器的,需要自己注册,在Controller中加入如下代码:

@InitBinder    
public void initBinder(WebDataBinder binder) {    
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");    
    dateFormat.setLenient(false);    
    binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}

转载于:https://my.oschina.net/ironwill/blog/680933

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值