當Apache Shiro趕上MultipartHttpServletRequest

####項目是SpringMVC框架,配置了SpringMVC文件上傳,同時使用了Apache Shiro。 ####能夠肯定配置是無誤的,表單也有enctype="multipart/form-data"屬性。 ####以下代碼,當用MultipartHttpServletRequest接收文件上傳請求時java

@RequestMapping(value = "addOrUpdate", method = RequestMethod.POST)
public String addOrUpdate(MultipartHttpServletRequest request) {
    // 業務邏輯
}

####會報告以下錯誤web

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

####暫時的解決方案以下apache

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

####fileUpload方法以下app

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過濾文件上傳引發的,不知道是否還有更好的解決方案(如經過某些配置能夠解決問題),之後研究了此問題再來更新。框架

###===========================更新=========================== ###===========================我是分割線===========================post

###通過調試發現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_以下code

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

####對應的添加頁面以下orm

<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));
}
相關文章
相關標籤/搜索