GWA2吉娃兔🐇Java中的文件上傳表單處理若干問題-2

去年(2020年)秋天写了上一篇:GWA2吉娃兔🐇Java中的文件上傳表單處理若干問題( https://ufqi.com/blog/gwa2-java-file-upload-issues/ ),随着我们持续不断的研发推进、精益求精,发现在 GWA2Java 中處理文件上傳的HTML表單被稱爲是“客貨混裝”的HTTP請求處理时,还有一些额外的问题需要再补充。兹详述于下,备忘备查。

(问题1-7请参考此前一篇Blog)

8. 数组型数据的接收与处理

在GWA2 Java中,为上传文件当HTML的表单类型被设置成 enctype 屬性為 multipart/form-data , request.getParameter 方法失效,同样地类似方法 request.getParameterValues 也失效了,如此以来,获取类似 多个 checkbox 这样的HTML form的输入,就成了问题。为此,我们需要再扩展一下之前使用 FormItems 来接管 request的相关属性的方法。

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; Object lastVal;
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”);
lastVal = request.getAttribute(iname);
if(lastVal != null){
// checkbox or multiple select
if(lastVal instanceof String[]){
String[] tmpArr = (String[])lastVal;
String[] tmpArr2 = new String[tmpArr.length+1];
for(int si=0; si<tmpArr.length; si++){
tmpArr2[si] = tmpArr[si];
}
tmpArr2[tmpArr.length] = ivalue;
request.setAttribute(iname, tmpArr2);
}
else{
String[] tmpArr = new String[2];
tmpArr[0] = String.valueOf(lastVal); tmpArr[1] = ivalue;
request.setAttribute(iname, tmpArr);
}
}
else{
request.setAttribute(iname, ivalue);
}
//debug(“ctrl/user: iname:”+iname+”, ivalue:”+ivalue+” lastVal:”+lastVal);
}
else{
debug(“ctrl/user: not form field: iname:”+item.getFieldName()+”, ivalue:”+item.getString().length());
}
}

使用 lastVal, 来检测是否同一个key的键值被赋予多个赋值,如果时,就启用一个数列来存储。相关代码在 github/wadelau/GWA2  ( https://github.com/wadelau/GWA2 )上可以获取。
该应用的场景是一个Form中,既有多选框,也有文件上传。

对应地,我们也在相关GWA2 的基础设施组件 comm/Wht 中增加了针对Form 的数列型数据的接收处理,方法名为
Wht.getArray(request, fieldName)
以此来接收和处理类似 multi select和check box类型的输入。

9. 多文件同时上传的优化处理

针对服务器端接收处理文件上传的相关组件,已经非常成熟,拿来用即可。如前所述,我们在GWA2 Java中处理文件的模块主要来自 Apache commons-fileupload-1.4.jar , 一并的也要引入 Apache commons-io-2.7.jar。

在一些细节上,还是有可深究的地方。默认情况下,我们通过 inc/FileSystem 中的一个 upload 方法来处理这些细节。针对 upload这个方法,预期的效果是给定一个上传的 form字段名称,然后返回一个保存后的文件路径,形式如:
formFieldA -> filePathInDisk

如果是多个文件呢?之前的方法是 upload 返回一个数组,包括多个地址,相当于:
[formFieldA, formFieldB] -> [filePathInDisk, filePathInDisk]

此时处理两个以上的文件上传时,它是能够完成预期目标的,可是,如果要更新其中一个文件时,就会出错。由于Form字段名称对应的磁盘文件路径,只有顺序,而没有最终预期的key/value 形式,当修改或更新其中一个文件时,总是返回形式为:
formFieldA -> filePathInDisk

这与只上传一个文件的情形是没法区分的。需要改正、优化。预期的是返回一个key/value形式的 formField/diskFilePath 。

// parses the request’s content to extract file data
@SuppressWarnings(“unchecked”)
List<FileItem> formItems = preFormItems;
if(formItems == null || formItems.size() ==0){
formItems = upload.parseRequest(request);
}
if (formItems != null && formItems.size() > 0){
// iterates over form’s fields
String fieldName, itemName, fileName, suffix, filePath;
File storeFile = null;
String showPath = UPLOAD_DIRECTORY + File.separator + relativePath;
if(!relativePath.endsWith(File.separator)){ showPath += File.separator; }
for (FileItem item : formItems){
// processes only fields that are not common form fields
if (!item.isFormField()){
fileName = “”;
fieldName = item.getFieldName(); itemName = item.getName();
if(itemName != null && !itemName.equals(“”)){
suffix = “”;
if(itemName.lastIndexOf(“.”)>0){
suffix = itemName.substring(itemName.lastIndexOf(“.”), itemName.length());
}
fileName = UUID.randomUUID().toString().replaceAll(“-“,””) + suffix;
filePath = uploadPath + File.separator + fileName;
debug(Log_Tag+” upload: filePath:”+filePath+” itemName:”+itemName);
// saves the file on disk
storeFile = new File(filePath);
item.write(storeFile);
fileName = showPath + fileName;
}
else{
fileName = “”;
debug(Log_Tag+”upload: skip empty itemName.”+itemName);
}
hmResult.put(fieldName, fileName);
}
else{
//debug(Log_Tag+” upload: form field item:”+item);
}
}
}
else{
debug(Log_Tag+” upload: formItems:”+formItems);
}

新增了 fieldName 字段,在返回时,将 Form fieldName 与 diskFilePath 以 key/value 形式严格对应起来,由返回 String 后者 String数组,改为返回 HashMap。如此以来,则可以解决同时上传多个文件,而不依赖顺序来对应所上传的文件,同时,当修改时,也可以避免所跳过的文件产生的顺序异常。完整功能的相关代码在 github/wadelau/GWA2  ( https://github.com/wadelau/GWA2 )上可以获取。

由于方法返回值的修改,不兼容此前版本,建议老版本的用户升级时,使用方法重载后者命名新方法的形式引入新功能。比如,在最近的项目 Boss选址 ( bossxuanzhi.com ) 中,我们就面临要使用命名新方法来兼容前期使用旧方法的 upload 和后期采用新方法的 uploadMultiple 。
如果是在新项目中,建议直接使用即可,没有向前兼容的需求。

 


-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 Native App, 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
轻松启动, 快速产出.

 


 

Boss选址( bossxuanzhi.com )是汇成产业服务(汇成产服)提供的在线服务,是服务政府投融资、招商、运营的平台型公司. 汇成产服公司定位:一、专业的政府招商代理服务机构,二、企业选址服务机构,三、企业咨询管理服务平台。

 

( https://ufqi.com/blog/gwa2-java-file-upload-issues-2nd/ )

 

此条目发表在-GWA2, 编程技术, 计算机技术分类目录,贴了, , , , 标签。将固定链接加入收藏夹。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

Captcha Code