JFinal使用POST及GET,getPara()相关问题

@JFinal 你好,我发现了一些很有趣的事情,

1.在使用POST上传文件及文本参数时,后台要获取文本参数,必须先获取文件,不然文本参数为null,测试代码如下:

public void testPost() {
    getFile();
    String a = getPara("a");
    renderText(a);
}

2.接口仅需要上传文本参数时,如果使用GET方式,后台可正确接收到文本参数,但使用POST方式时,后台获取的文本参数将为null,代码如下:

使用get可接收到文本参数:

public void testGet() {
    String a = getPara("a");
    renderText(a);
}

当使用POST方式时,将获取不到文本参数,尽管此时我没有上传文件,但为了获取到文本参数,我必须手动调用一下getFile()方法,才能成功获取:

public void testGet() {
    getFile();
    String a = getPara("a");
    renderText(a);
}

但是因为加上了getFile(),我再想使用GET调用时,就会报异常:

java.lang.RuntimeException: java.io.IOException: Posted content type isn't multipart/form-data

程序会默认其为POST调用的,content type类型不正确,此时,此接口将不能使用GET调用。

即:POST,GET不能共存。

因为处于项目开发阶段,时间有限,所以没深入探究源码,请问,为什么会造成这种现象,有没有何种解决方式?

评论区

JFinal

2017-06-29 11:53

这个需要了解一下 http 协议的 multipart 请求规范,http 表单提交主要有两类:
1:普通表单提交,即普通的 request 请求
2:multipart request 表单提交

特别注意第二种提交是上传文件必须的提交类型,需要为 form 表单设置 enctype="multipart/form-data" 属性

第二种表单提交到服务器以后的 HttpServletRequest 对象是不能直接 request.getParameter(...) 的,因为里头的数据没有被解析

这时各种 file 解析的第三方就上场了,例如 cos、fileupload 这类项目,还有很多这种:https://www.oschina.net/project/tag/139/fileupload?company=0&sort=score&tag=139&lang=19&recommend=false

所以,当请求是 multipart 时,必须要对 request 这个对象进行解析,才可以让 request.getParameter(...) 得到数据

而 jfinal 对 multipart 的解析在 getFile(...) 这类方法中进行,所以需要首先调用 getFile(...) 随后才可以调用 getPara(...),本质就是要先解析,才可以 getPara(...),这个问题在 jfinal 手册上有红色字体说明

当然,jfinal 可以在框架内部自动判断请求是否为 multipart 请求,然后自动事先解析,那么用户就不需要关心 getFile 是在前还是在后的问题了,但会引发两个问题:
1:getFile(path, ...) 方法可以传入一个 path 参数,用于指令解析出来的文件存放在哪里,如果 jfinal 帮忙去调用 getFile(...),是无法得到这个 path 参数的。
如果 jfinal 一定要插手此事,只能是先存放在一个固定的临时目录,然后由用户随后自己再手动移动该文件

2:jfinal 需要在每次请求到来时都去判断请求是否为 multi part 类型,而这种请求实际上极少发生,为了极少发生的事情,每每去判断,多少会损失点性能

综上,设计是一个不断权衡取舍的过程,很多纠结

JFinal

2017-06-29 11:54

最后再补充一句,文件上传功能要先调用 getFile(...) 随后才能调用 getPara(...) 的问题在 jfinal 手册上有红色字体强调过

aloneJFinal

2017-06-29 13:27

@JFinal 谢谢及时解答,很清楚。我本身有一些疏忽,使用的Postman调试工具,POST提交会默认选择multipart/form-data类型,手动切换其他POST类型,比如:x-www-form-urlencoded就可以了,我列举的案例正好是你所说的两种情况,普通request及multipart request,感谢!!!

蓝胖纸

2019-05-29 11:42

@JFinal 波总 如果HttpKit.post(url, data)方法调用的时候参数需要以x-www-form-urlencoded方式传输要怎么使用

蓝胖纸

2019-05-29 11:55

@JFinal 用postman测试了下,参数是以raw方式的接口可以直接使用HttpKit.post(url, JSON.toJSONString(map))方式进行调用,但是x-www-form-urlencoded的却不行,我看源码里也有设置conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded"),不是太懂,希望您能解答一下

Mavenjay

2019-08-23 10:50

我该如何避免 getFile() 自动上传到upload目录? 因为我现在只想往OSS上面上传

热门反馈

扫码入社