JFinal

登录 注册

关于getFile()的一些看法和建议

如题。

在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的实现类,关系如下:

wKioL1g85qyTt9gAAABZIaaToZg320.png

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()方法中,仅首次调用时进行解析装载,那样就能愉快的实现文本参数和文件参数分离了。

波哥觉得如何?

评论

  • 09-14 00:19
    愿望非常好,这也是多年前我做这个功能时希望的样子,但是不解析就无法取到文本参数,这个是由 http 规范决定的

    其实这个问题很好验证,你可以将 MultipartRequest 的代码全部 copy 出来,改造成自己需要的样子,然后通过下面的代码让其生效就好:
    inv.getController().setHttpServletRequest(myMultipartRequest)

    上面的代码即可将你自己解析出来的 myMultipartRequest 再注入 controller 中以供后面使用,仍然是用你在本贴中的拦截器来做
  • 09-14 11:05
    @JFinal 感谢,已进行验证,确实不行
  • 09-14 11:24
    @aloneJFinal 参数与上传文件本身是被包含在整个 http 封装好的流里面的,解析这个流才能得到参数与文件内容,而一旦解析,文件和参数是同时被解析的,参数存放的位置也是不确定的,或许在文件之中某个位置
  • 发送