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/ )

 

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