如题。
在JFinal中对于文件上传后台使用getFile()系列方法用于获取文件,当文件上传又需要携带文本参数时,必须先调用getFile()后才能使用getPara()系列方法获取参数,不然将获取不到文本参数。
跟了一下代码,发现getPara()系列的方法实质:
public String getPara(String name) { return request.getParameter(name); }
这个request是HttpServletRequest。当上传文件时,http的Content-Type为multipart/form-data,getFile()方法中会将HttpServletRequest转换为自定义MultipartRequest类,MultipartRequest类是HttpServletRequestWrapper的子类,HttpServletRequestWrapper类则是HttpServletRequest的实现类,关系如下:
MultipartRequest中重写了getParameter方法:
public String getParameter(String name) { return multipartRequest.getParameter(name); }
此时将从http multipart/form-data的body中解析获取对应的文本参数。
实际开发过程中,我们经常会将文本参数和文件一起传递,并且是有些时候,需要先验证文本参数,然后才决定是否接受文件,此时,为了接收文本参数,我就必须先接收文件,接收文件完成后,发现文本参数并不符合要求,则需要废弃文件流,觉得这样不太好,会白白浪费一些资源,文件小还好,文件大的话比如500M、1G就会很影响体验。
我理想中的方式是:文本参数和文件参数是分开处理的,没有必然的耦合,能互不影响。
于是我想做出一些修改,创建一个全局的拦截器,当发现是multipart/form-data类型时,手动将HttpServletRequest转换为MultipartRequest:
@Override public void intercept(Invocation inv) { BaseController bc = (BaseController) inv.getController(); HttpServletRequest request = bc.getRequest(); if ("POST".equalsIgnoreCase(request.getMethod()) && request.getContentType().contains("multipart/form-data")) { if (request instanceof MultipartRequest == false) { request = new MultipartRequest(request); bc.setHttpServletRequest(request); } } inv.invoke(); }
但是,后来悲催的发现在MultipartRequest的构造方法中已经完成了对文件的获取,所以看波哥下个版本能不能酌情优化一下MultipartRequest解析装载文件这一段,将其移出构造器,放入getFiles()方法中,仅首次调用时进行解析装载,那样就能愉快的实现文本参数和文件参数分离了。
波哥觉得如何?
其实这个问题很好验证,你可以将 MultipartRequest 的代码全部 copy 出来,改造成自己需要的样子,然后通过下面的代码让其生效就好:
inv.getController().setHttpServletRequest(myMultipartRequest)
上面的代码即可将你自己解析出来的 myMultipartRequest 再注入 controller 中以供后面使用,仍然是用你在本贴中的拦截器来做