GWA2吉娃兔🐇Java中的文件上传表单处理若干问题

在 GWA2Java 中处理文件上传的HTML表单被称为是“客货混装”的HTTP请求处理。

文件上传处理是HTTP Web开发中较为特殊的应用,对开发者有一定的要求。无论是流行的PHP,Aspx或者JSP都需要一定的处理技巧。由于实在想不起来10多年前是如何赤手纯代码来处理客货混装的HTML文件上传表单,这次还是详细地记录一次,以备再过些时日忘却了而备查。

还有一层考虑是,在处理HTML的文件上传表单时,需要考虑与 GWA2Java的融合,涉及到GWA2 的文件处理的核心模块,因此也需要或者也是检视GWA2架构设计的一次极好的机会。
对此前的 GWA2 Java项目的巡视,我们发现已经有一些项目涉及到文件上传,但基本上多数是使用Ajax异步上次等,回避了“客货混装”模式,某个HTML表单只负责文件上传,而另外一个表单再收集其他数据。

所以,这次要在 GWA2Java 中更好的整合进文件上传,并且是客货混装模式——处理一个表单,里面同时包括两个字段:张三的姓名文字和张三的头像图片。

1. 浏览器客户端 HTML表单中enctype

如果需要在浏览器客户端的HTML表单中进行文件上传,需要明确显式地指定 Form元素的 enctype 属性为 multipart/form-data 。

2. 服务器端接收处理文件上传的第三方组件

基于 Apache Tomcat的 Java Web Server,进行服务器端的文件上传处理,推荐使用的组件是 Apache commons-fileupload-1.4.jar , 一并的也要引入 Apache commons-io-2.7.jar。

3. HTTP Request.getParameter 失效

儅客户端使用文件上传的表单递交数据时,Java Web Server中常规的 Servlet 对象 HTTPRequest的主要方法 request.getParameter 就失效。这也是普通程序无法处理客货混装的原因之一。

取而代之的,儅 enctype=multipart/form-data , 需要通过第三方组件获取到相应的表单参数。
在 GWA2 中,其中的路由模块严重依赖HTTP Request的参数,这时候,需要将主要路由参数放入Form的Action属性中。
可以改进的另外一个方法是,通过引入 Apache commons-fileupload 的相关对象,便利 FormItems 对象,从而获得表单中的常规非文件字段,文本文件字段的名称和值。

遍历FormItems获得HTTP Request请求参数之后,再通过 request.setAttribute写回到当前Request对象,如此即可巧妙地弥补 request.getParameter 失效的问题。
由于在 GWA2Java 中,获取外部参数通常由 Wht.get 的方法进行,这个方法除了调用 request.getParameter 之外,还会进一步地的访问 request.getAttribute , 从而实现了对 request.setAttribute 的访问。再进一步地的 Wht.get 还会对访问数据做一些基本的安全检查。

样例代码:

ServletFileUpload sfileupld = new ServletFileUpload((new DiskFileItemFactory()));
formItems = sfileupld.parseRequest(request); // can only be parsed once!
if (formItems != null && formItems.size() > 0){
String iname, ivalue; byte[] bytes;
for (FileItem item : formItems){
// processes only fields that are common form fields
if (item.isFormField()){
bytes = item.getFieldName().getBytes(“ISO-8859-1”); // why 8859?
iname = new String(bytes, “UTF-8”);
bytes = item.getString().getBytes(“ISO-8859-1”);
ivalue = new String(bytes, “UTF-8”);
request.setAttribute(iname, ivalue);
//debug(“ctrl/item: iname:”+iname+”, ivalue:”+ivalue);
}
}
}

 

4. HTML表单上传request 能且仅能被parse一次

上文中提到的获取 FormItems 需要从 HTTP Request中提取,

List<FormItem> formItems = uploadInstance.parseRequest(request);

这里的Request,只能被 parseRequest 执行一次,如果在同一次请求处理程序中,再次对这个 request 执行 parseRequest 时,就会返回异常为空的错误。
因此,儅我们需要在程序顶部通过便利 FormItems 设置 request.setAttribute 时,还需要保留 FormItems 作为全局对象,在后面这里处理实际上传文件时使用,避免再次调用 parseRequest 产生为空的错误异常。

5. 挥之不去的字符转码: 从 ISO-8859-1 到 UTF-8

从心里上,我们是抗拒在代码中进行字符集转码的,所以从一开始,我们在 GWA2Java 中进行了前后端统一全流程一贯地使用UTF-8字符集,从而避免在系统程序内做无谓的转码工作。(参考:-GWA2 Java版本的i18n/中文编码/乱码问题,https://ufqi.com/blog/gwa2-java-i18n/ 

偏偏这里儅使用客货混装模式进行文件上传时,通过parseRequest出来的 FormItem 其中的非ASCII字符的编码是 ISO-8859-1 ,对于像 GWA2Java 这样默认的 UTF-8 环境,字符集转码成为迫不得已的事情。

6. 文件上传处理方法的归置

在 GWA2 的架构设计中,文件上传功能,归属于文件模块,引入系统的接口文件是 inc/FileA , 针对不同的文件系统,有不同的文件类来实现 inc/FileDirver , 如 默认的文件处理是 Linux 的 inc/FileSystem .

在归属上,这些 inc 目录下的类及其方法是“大家闺秀”,一般不参与到具体业务处理程序的,只能通过统一界面接口 inc/WebApp 来调用。因此理想的是调用文件上传的逻辑流程大致为:

ctrl/a.jsp –> mod/ModA –> inc/WebApp –> inc/FileA –> inc/FileSystem .

由于文件上传,属于非常规的“操作”需求,另外一种非标准的捷径是,在 mod/ModA 中直接实例化 inc/FileSystem , 从而便利地触发对 upload 方法的运用。但这只针对具体的项目可行,且不需要可移植性。比如如果宿主系统不是 Linux, 那就不能实例化 inc/FileSystem , 相应地可能需要实例化 inc/WindowsFileSystem 来处理宿主环境是 Windows 的文件上传。

7. 有进有出,文件删除的操作

在此之前,核心接口类 inc/WebApp 中定义了 readObject/writeObject 用来读写非数据库源的数据。其中 inc/FileA 中相应地定义了 read/write 方法,只是还没有对应的删除方法 rm 的实现。

接著这个机会,我们归置并实现了 inc/FileA, inc/FileDriver 和 inc/FileSystem 三个类的 rm 方法,同时改造 inc/WebApp.rmBy 方法,将上述方法进行对接。

inc/WebApp.rmBy(“file:Path_To_File”) –> inc/FileA.rm –> inc/FileSystem.rm .

 GWA2Java, GWA2 就是这样通过一个又一个项目实践,不断丰富完善,日益健壮强大,儅融合和沉淀足够多的智慧和精华,一定能取得更大的成就。我们在 UfqiWork 有福工坊 ( https://ufqi.com/work/ )上首先实现了 GWA2Java 处理文件上传的客货混装模式。


-GWA2 吉娃兔 是”通用网络应用架构( General Web Application Architeture, https://ufqi.com/dev/gwa2/ )”,基于 -GWA2 可以轻便构建各种网络应用程序,
包括复杂的在线购物商城、在线医疗、在线教育、 旅游交易平台、社群或者社交网站和新闻资讯网站等,
也包括各种企事业单位网上门户,在线交互及服务作业系统等.
还可以包括为NativeApp做服务器端支持, 甚至是WebApp的全部.
-GWA2 是为数不多的支持跨开发语言的应用框架,目前支持 -Java, -PHP, -Perl, -Aspx and -Python .

-GWA2 is a “General Web Application Architecture” and based on -GWA2 developers can easily build a variety of network applications,
including complex online shopping malls, online medical services, online teaching, travel trading platforms, community or social networking sites and news information sites, etc.
Also the applications include various online portals of enterprises and institutions, online interaction and service operations systems.
Moreover it contains server-side support for NativeApp, or even all of the WebApp.
-GWA2 is one of the web frameworks which provide cross-language support for -Java, -PHP, -Perl, -Aspx and -Python at present.

-GWA2 is E.A.S.Y 
Easy Along, Swift Yield
轻松启动, 快速产出.


ufqiwork-logo

有福工坊UfqiWork 是一个在线服务交易平台。( https://ufqi.com/work/ )
有福工坊提供在线分类服务信息,致力于在线撮合服务交易的买方和卖方,并为买方、卖方提供“行准”服务,居间担保服务交易。行准服务的提供方为居间交易的第三方。有福工坊的服务交易平台为整个服务交易流程的第四方。

-R/32ST

https://ufqi.com/blog/gwa2-java-file-upload-issues/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章