如果表單里面包括上傳文件的 input 標(biāo)簽 這個(gè)時(shí)候就不能用beanUtils
1暂氯、文件上傳的原理分析
1.1文件上傳的必要前提:
a侣滩、提供form表單证逻,method必須是post
b、form表單的enctype必須是multipart/form-data
c找筝、提供input type="file"類的上傳輸入域
注意:文件上傳不能以String傳輸 以字節(jié)流形式傳輸(圖片)
1.2enctype屬性
作用:告知服務(wù)器請求正文的MIME類型。(請求消息頭:Content-Type作用是一致的)
可選值:
application/x-www-form-urlencoded(默認(rèn)):
正文:name=admin&password=123
服務(wù)器獲取數(shù)據(jù):String name = request.getParameter("name");
multipart/form-data:
服務(wù)器獲取數(shù)據(jù):request.getParameter(String)方法獲取指定的表單字段字符內(nèi)容慷吊,但文件上傳表單已經(jīng)不在是字符內(nèi)容袖裕,而是字節(jié)內(nèi)容,所以失效罢浇。
2陆赋、借助第三方的上傳組件實(shí)現(xiàn)文件上傳
2.1 fileupload概述
fileupload是由apache的commons組件提供的上傳組件沐祷。它最主要的工作就是幫我們解析request.getInputStream()。
導(dǎo)入commons-fileupload相關(guān)jar包
commons-fileupload.jar攒岛,核心包赖临;
commons-io.jar,依賴包灾锯。
2.2 fileupload的核心類有:
DiskFileItemFactory兢榨、ServletFileUpload、FileItem顺饮。
a吵聪、解析原理
2.3 fileupload簡單應(yīng)用
使用fileupload組件的步驟如下:
1.創(chuàng)建工廠類DiskFileItemFactory對象:
DiskFileItemFactory factory = new DiskFileItemFactory()
2.使用工廠創(chuàng)建解析器對象:
ServletFileUpload fileUpload = new ServletFileUpload(factory)
3.使用解析器來解析request對象:
List<FileItem> list = fileUpload.parseRequest(request)
FileItem對象對應(yīng)一個(gè)表單項(xiàng)(表單字段)〖嫘郏可以是文件字段或普通字段
boolean isFormField():判斷當(dāng)前表單字段是否為普通文本字段吟逝,如果返回false,說明是文件字段赦肋;
String getFieldName():獲取字段名稱块攒,例如:<input type=”text” name=”username”/>,返回的是username佃乘;
String getString():獲取字段的內(nèi)容囱井,如果是文件字段,那么獲取的是文件內(nèi)容趣避,當(dāng)然上傳的文件必須是文本文件庞呕;
String getName():獲取文件字段的文件名稱;(a.txt 101.jpg)
String getContentType():獲取上傳的文件的MIME類型程帕,例如:text/plain住练。
int getSize():獲取上傳文件的大小骆捧;
InputStream getInputStream():獲取上傳文件對應(yīng)的輸入流澎羞;
void write(File):把上傳的文件保存到指定文件中。
delete();**
4敛苇、文件上傳時(shí)要考慮的幾個(gè)問題(經(jīng)驗(yàn)分享)
a妆绞、保證服務(wù)器的安全
把保存上傳文件的目錄放在用戶直接訪問不到的地方。
b枫攀、避免文件被覆蓋
讓文件名唯一即可
c括饶、避免同一個(gè)文件夾中的文件過多
方案一:按照日期進(jìn)行打散存儲(chǔ)目錄
方案二:用文件名的hashCode計(jì)算打散的存儲(chǔ)目錄:二級目錄
d、限制文件的大欣凑恰:web方式不適合上傳大的文件
單個(gè)文件大型佳妗:
ServletFileUpload.setFileSizeMax(字節(jié))
總文件大小:(多文件上傳)
ServletFileUpload.setSizeMax(字節(jié))
e蹦掐、上傳字段用戶沒有上傳的問題
通過判斷文件名是否為空即可
f技羔、臨時(shí)文件的問題
DiskFileItemFactory:
作用:產(chǎn)生FileItem對象
內(nèi)部有一個(gè)緩存僵闯,緩存大小默認(rèn)是10Kb。如果上傳的文件超過10Kb藤滥,用磁盤作為緩存鳖粟。
存放緩存文件的目錄在哪里?默認(rèn)是系統(tǒng)的臨時(shí)目錄拙绊。
FileItem.write(File)
如果自己用IO流實(shí)現(xiàn)的文件上傳向图,要在流關(guān)閉后,清理臨時(shí)文件标沪。
FileItem.delete();
setHeaderEncoding方法:由于瀏覽器在提交FORM表單時(shí)榄攀,會(huì)將普通表單中填寫的文本內(nèi)容傳遞給服務(wù)器,對于文件上傳字段金句,除了傳遞原始的文件內(nèi)容外檩赢,還要傳遞其文件路徑名等信息。如果在使用Apache文件上傳組件時(shí)遇到了中文字符的亂碼問題趴梢,一般都是沒有正確調(diào)用setHeaderEncoding方法的原因漠畜。
一般在Servlet中使用如下設(shè)置:
servletFileUpload.setHeaderEncoding("utf-8");
getName方法用于獲得文件上傳字段中的文件名,如果FileItem類對象對應(yīng)的是普通的表單字段坞靶,getName方法將返回null,即使用戶沒有通過網(wǎng)頁表單中的文件字段傳遞任何文件蝴悉,但只要設(shè)置了文件表單字段的name屬性彰阴,瀏覽器也會(huì)將文件字段的信息傳遞給服務(wù)器,只是文件名和文件內(nèi)容部分都為空拍冠,但這個(gè)表單字段仍然對應(yīng)一個(gè)FileItem對象尿这,此時(shí)getName方法返回結(jié)果為”“字符串,這一部分在使用的時(shí)候需要注意一下庆杜。值得注意的是射众,如果用戶使用windows系統(tǒng)上傳文件,瀏覽器將傳遞該文件的完整路徑晃财;如果使用linux或Unix系統(tǒng)上傳文件叨橱,瀏覽器將只傳遞該文件的名稱部分。
使用方式如下所示:
當(dāng)我們要選取非文件字段的文本值的時(shí)候 需要用如下的寫法:
本文主要借鑒 https://blog.csdn.net/gaoying_blogs/article/details/64919204
以及 https://blog.csdn.net/soft_xiaohui/article/details/5904785 這兩篇文章断盛。