這篇文章主要講解了“Java中文件上傳表單問(wèn)題怎么處理”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“Java中文件上傳表單問(wèn)題怎么處理”吧!
創(chuàng)新互聯(lián)建站專(zhuān)注于千山企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站開(kāi)發(fā),成都做商城網(wǎng)站。千山網(wǎng)站建設(shè)公司,為千山等地區(qū)提供建站服務(wù)。全流程按需定制制作,專(zhuān)業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)建站專(zhuān)業(yè)和態(tài)度為您提供的服務(wù)
文件上傳處理是HTTP Web開(kāi)發(fā)中較爲(wèi)特殊的應(yīng)用,對(duì)開(kāi)發(fā)者有一定的要求。無(wú)論是流行的PHP,Aspx或者JSP都需要一定的處理技巧。由於實(shí)在想不起來(lái)10多年前是如何赤手純代碼來(lái)處理客貨混裝的HTML文件上傳表單,這次還是詳細(xì)地記錄一次,以備再過(guò)些時(shí)日忘卻了而備查。
還有一層考慮是,在處理HTML的文件上傳表單時(shí),需要考慮與 GWA2Java的融合,涉及到GWA2 的文件處理的核心模塊,因此也需要或者也是檢視GWA2架構(gòu)設(shè)計(jì)的一次極好的機(jī)會(huì)。
對(duì)此前的 GWA2 Java項(xiàng)目的巡視,我們發(fā)現(xiàn)已經(jīng)有一些項(xiàng)目涉及到文件上傳,但基本上多數(shù)是使用Ajax異步上次等,回避了“客貨混裝”模式,某個(gè)HTML表單只負(fù)責(zé)文件上傳,而另外一個(gè)表單再收集其他數(shù)據(jù)。
所以,這次要在 GWA2Java 中更好的整合進(jìn)文件上傳,并且是客貨混裝模式——處理一個(gè)表單,裏面同時(shí)包括兩個(gè)字段:張三的姓名文字和張三的頭像圖片。
1. 瀏覽器客戶端 HTML表單中enctype
如果需要在瀏覽器客戶端的HTML表單中進(jìn)行文件上傳,需要明確顯式地指定 Form元素的 enctype 屬性為 multipart/form-data 。
2. 服務(wù)器端接收處理文件上傳的第三方組件
基於 Apache Tomcat的 Java Web Server,進(jìn)行服務(wù)器端的文件上傳處理,推薦使用的組件是 Apache commons-fileupload-1.4.jar , 一并的也要引入 Apache commons-io-2.7.jar。
3. HTTP Request.getParameter 失效
儅客戶端使用文件上傳的表單遞交數(shù)據(jù)時(shí),Java Web Server中常規(guī)的 Servlet 對(duì)象 HTTPRequest的主要方法 request.getParameter 就失效。這也是普通程序無(wú)法處理客貨混裝的原因之一。
取而代之的,儅 enctype=multipart/form-data , 需要通過(guò)第三方組件獲取到相應(yīng)的表單參數(shù)。
在 GWA2 中,其中的路由模塊嚴(yán)重依賴(lài)HTTP Request的參數(shù),這時(shí)候,需要將主要路由參數(shù)放入Form的Action屬性中。
可以改進(jìn)的另外一個(gè)方法是,通過(guò)引入 Apache commons-fileupload 的相關(guān)對(duì)象,便利 FormItems 對(duì)象,從而獲得表單中的常規(guī)非文件字段,文本文件字段的名稱(chēng)和值。
遍歷FormItems獲得HTTP Request請(qǐng)求參數(shù)之後,再通過(guò) request.setAttribute寫(xiě)回到當(dāng)前Request對(duì)象,如此即可巧妙地彌補(bǔ) request.getParameter 失效的問(wèn)題。
由於在 GWA2Java 中,獲取外部參數(shù)通常由 Wht.get 的方法進(jìn)行,這個(gè)方法除了調(diào)用 request.getParameter 之外,還會(huì)進(jìn)一步地的訪問(wèn) request.getAttribute , 從而實(shí)現(xiàn)了對(duì) request.setAttribute 的訪問(wèn)。再進(jìn)一步地的 Wht.get 還會(huì)對(duì)訪問(wèn)數(shù)據(jù)做一些基本的安全檢查。
樣例代碼:
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
這裏的Request,只能被 parseRequest 執(zhí)行一次,如果在同一次請(qǐng)求處理程序中,再次對(duì)這個(gè) request 執(zhí)行 parseRequest 時(shí),就會(huì)返回異常為空的錯(cuò)誤。
因此,儅我們需要在程序頂部通過(guò)便利 FormItems 設(shè)置 request.setAttribute 時(shí),還需要保留 FormItems 作爲(wèi)全局對(duì)象,在後面這裏處理實(shí)際上傳文件時(shí)使用,避免再次調(diào)用 parseRequest 產(chǎn)生爲(wèi)空的錯(cuò)誤異常。
5. 揮之不去的字符轉(zhuǎn)碼: 從 ISO-8859-1 到 UTF-8
從心裏上,我們是抗拒在代碼中進(jìn)行字符集轉(zhuǎn)碼的,所以從一開(kāi)始,我們?cè)?GWA2Java 中進(jìn)行了前後端統(tǒng)一全流程一貫地使用UTF-8字符集,從而避免在系統(tǒng)程序內(nèi)做無(wú)謂的轉(zhuǎn)碼工作。(參考:-GWA2 Java版本的i18n/中文編碼/亂碼問(wèn)題,https://ufqi.com/blog/gwa2-java-i18n/ )
偏偏這裏儅使用客貨混裝模式進(jìn)行文件上傳時(shí),通過(guò)parseRequest出來(lái)的 FormItem 其中的非ASCII字符的編碼是 ISO-8859-1 ,對(duì)於像 GWA2Java 這樣默認(rèn)的 UTF-8 環(huán)境,字符集轉(zhuǎn)碼成爲(wèi)迫不得已的事情。
6. 文件上傳處理方法的歸置
在 GWA2 的架構(gòu)設(shè)計(jì)中,文件上傳功能,歸屬于文件模塊,引入系統(tǒng)的接口文件是 inc/FileA , 針對(duì)不同的文件系統(tǒng),有不同的文件類(lèi)來(lái)實(shí)現(xiàn) inc/FileDirver , 如 默認(rèn)的文件處理是 Linux 的 inc/FileSystem .
在歸屬上,這些 inc 目錄下的類(lèi)及其方法是“大家閨秀”,一般不參與到具體業(yè)務(wù)處理程序的,只能通過(guò)統(tǒng)一界面接口 inc/WebApp 來(lái)調(diào)用。因此理想的是調(diào)用文件上傳的邏輯流程大致為:
ctrl/a.jsp –> mod/ModA –> inc/WebApp –> inc/FileA –> inc/FileSystem .
由於文件上傳,屬於非常規(guī)的“操作”需求,另外一種非標(biāo)準(zhǔn)的捷徑是,在 mod/ModA 中直接實(shí)例化 inc/FileSystem , 從而便利地觸發(fā)對(duì) upload 方法的運(yùn)用。但這只針對(duì)具體的項(xiàng)目可行,且不需要可移植性。比如如果宿主系統(tǒng)不是 Linux, 那就不能實(shí)例化 inc/FileSystem , 相應(yīng)地可能需要實(shí)例化 inc/WindowsFileSystem 來(lái)處理宿主環(huán)境是 Windows 的文件上傳。
7. 有進(jìn)有出,文件刪除的操作
在此之前,核心接口類(lèi) inc/WebApp 中定義了 readObject/writeObject 用來(lái)讀寫(xiě)非數(shù)據(jù)庫(kù)源的數(shù)據(jù)。其中 inc/FileA 中相應(yīng)地定義了 read/write 方法,只是還沒(méi)有對(duì)應(yīng)的刪除方法 rm 的實(shí)現(xiàn)。
接著這個(gè)機(jī)會(huì),我們歸置並實(shí)現(xiàn)了 inc/FileA, inc/FileDriver 和 inc/FileSystem 三個(gè)類(lèi)的 rm 方法,同時(shí)改造 inc/WebApp.rmBy 方法,將上述方法進(jìn)行對(duì)接。
inc/WebApp.rmBy(“file:Path_To_File”) –> inc/FileA.rm –> inc/FileSystem.rm .
GWA2Java, GWA2 就是這樣通過(guò)一個(gè)又一個(gè)項(xiàng)目實(shí)踐,不斷豐富完善,日益健壯強(qiáng)大,儅融合和沉澱足夠多的智慧和精華,一定能取得更大的成就。我們?cè)?UfqiWork 有福工坊 ( https://ufqi.com/work/ )上首先實(shí)現(xiàn)了 GWA2Java 處理文件上傳的客貨混裝模式。
感謝各位的閱讀,以上就是“Java中文件上傳表單問(wèn)題怎么處理”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)Java中文件上傳表單問(wèn)題怎么處理這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!