前言
我們?cè)陂_發(fā)web應(yīng)用時(shí),肯定要為用戶提供上傳的功能,比如用戶上傳一張圖像作為頭像等。為了能上傳文件,我們必須將表單的method設(shè)置為post,將enctype設(shè)置為multipart/form-data
。只有在這種情況下,瀏覽器才會(huì)把用戶選擇文件的二進(jìn)制數(shù)據(jù)發(fā)送給服務(wù)器。這篇文章就對(duì)struts2框架中的上傳功能進(jìn)行詳細(xì)的總結(jié),下面話不多說了,來一起看看詳細(xì)的介紹吧。
struts2的文件上傳
struts2并未提供自己的請(qǐng)求解析器,也就是說,struts2不會(huì)自己去處理multipart/form-data的請(qǐng)求,它需要調(diào)用其它上傳框架來解析二進(jìn)制請(qǐng)求數(shù)據(jù),但struts2在原有的上傳解析器基礎(chǔ)上做了進(jìn)一步封裝,更進(jìn)一步簡化了文件上傳。
在struts2的default.properties
配置文件中,可以看到這樣的配置代碼:
1
2
3
4
5
6
7
8
|
### parser to handle http post requests, encoded using the mime-type multipart/form-data # struts.multipart.parser=cos # struts.multipart.parser=pell # struts.multipart.parser=jakarta-stream struts.multipart.parser=jakarta # uses javax.servlet.context.tempdir by default struts.multipart.savedir= struts.multipart.maxsize= 2097152 |
上述代碼主要用于配置struts2上傳文件時(shí)的上傳解析器。struts2的封裝隔離了底層文件上傳組件的區(qū)別,開發(fā)者只要在此配置文件上傳所使用的解析器,就可以輕松地在不同的文件上傳框架之間切換。
struts2默認(rèn)使用jakarta上傳解析器,當(dāng)然了,如果你不喜歡,你也可以換成別的。下面就通過代碼來實(shí)現(xiàn)一個(gè)簡單的基于struts2的文件上傳功能。
實(shí)現(xiàn)文件上傳的action
前臺(tái)頁面:
1
2
3
4
5
|
<form action= "upload" method= "post" enctype= "multipart/form-data" > title:<input type= "text" name= "title" ><br> file:<input type= "file" name= "upload" ><br> <input type= "submit" value= "submit" > </form> |
action類:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
public class uploadaction extends actionsupport { private string title; private file upload; private string uploadcontenttype; private string uploadfilename; private string savepath; public void setsavepath(string value) { this .savepath = value; } private string getsavepath() { string realpath = servletactioncontext.getservletcontext().getrealpath( "/web-inf/" + savepath); return realpath; } public void settitle(string value) { this .title = value; } public string gettitle() { return title; } public void setupload(file value) { this .upload = value; } public file getupload() { return upload; } public void setuploadcontenttype(string value) { this .uploadcontenttype = value; } public string getfilecontenttype() { return uploadcontenttype; } public void setuploadfilename(string value) { this .uploadfilename = value; } public string getuploadfilename() { return uploadfilename; } @override public string execute() throws exception { fileoutputstream fos = new fileoutputstream(getsavepath() + "\\" + getuploadfilename()); fileinputstream fis = new fileinputstream(getupload()); byte [] buffer = new byte [ 1024 ]; int len = 0 ; while ((len = fis.read(buffer)) > 0 ) { fos.write(buffer, 0 , len); } fis.close(); fos.close(); return success; } } |
struts.xml配置文件:
1
2
3
4
5
6
7
|
< package name= "upload" extends = "struts-default" > <action name= "upload" class = "com.jellythink.practise.uploadaction" > <param name= "savepath" >/upload</param> <result name= "success" >/success.jsp</result> <result name= "input" >/index.jsp</result> </action> </ package > |
對(duì)于action類中,包含了兩個(gè)特別的屬性:
- uploadcontenttype
- uploadfilename
這兩個(gè)屬性分別用于封裝上傳文件的文件名、上傳文件的文件類型。對(duì)于struts2來說,如果form表單中包含一個(gè)name屬性為xxx的文件域,則對(duì)應(yīng)的action需要使用三個(gè)屬性來封裝該文件域的信息:
- 類型為file的xxx屬性封裝了該文件域?qū)?yīng)的文件內(nèi)容;
- 類型為string的xxxfilename屬性封裝了該文件域?qū)?yīng)的文件的文件名;
- 類型為string的xxxcontenttype屬性封裝了該文件域?qū)?yīng)的文件的文件類型。
通過上面的開發(fā)過程,可以看出通過struts2實(shí)現(xiàn)文件上傳確實(shí)是一件簡單的事情。我們需要做的事情就是將文件域與action中一個(gè)類型為file的屬性關(guān)聯(lián),就可以輕松訪問到上傳文件的文件內(nèi)容,至于struts2如何使用multipart解析器,對(duì)開發(fā)者完全透明。
手動(dòng)實(shí)現(xiàn)文件過濾
很多時(shí)候,web應(yīng)用不允許用戶自由上傳,我們需要對(duì)用戶上傳的文件類型,文件大小進(jìn)行限制,因此必須在文件上傳過程中進(jìn)行文件過濾。下面就先手動(dòng)實(shí)現(xiàn)上傳文件過濾。
在struts.xml中配置一個(gè)新的參數(shù),表示支持的上傳類型:
1
|
<param name= "allowtypes" >image/png,image/gif,image/jpeg</param> |
在action中添加驗(yàn)證函數(shù):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
// 進(jìn)行驗(yàn)證 @override public void validate() { string filterresult = filtertype(getallowtypes().split( "," )); if (filterresult != null ) { addfielderror( "upload" , "您要上傳的文件類型不正確!" ); } } public string filtertype(string[] types) { string filetype = getfilecontenttype(); for (string type : types) { if (type.equals(filetype)) { return null ; } } return error; } |
這只是實(shí)現(xiàn)了類型的判斷,然后在根據(jù)file類的length()
方法,來實(shí)現(xiàn)大小的驗(yàn)證。但是好麻煩,接下來就說一種更簡單的說法。
攔截器實(shí)現(xiàn)文件過濾
struts2提供了一個(gè)文件上傳的攔截器,通過配置攔截器可以更輕松地實(shí)現(xiàn)文件過濾。struts2中文件上傳的攔截器fileupload,為了讓該攔截器起作用,只需要在該action中配置該攔截器引用即可。
配置fileupload攔截器時(shí),可以為其指定兩個(gè)參數(shù):
- allowedtypes:該參數(shù)指定允許上傳的文件類型,多個(gè)文件類型之間以英文逗號(hào)隔開
- maximumsize:該參數(shù)指定允許上傳的文件大小,單位是字節(jié)
1
2
3
4
5
6
7
8
9
10
|
<!-- 配置fileupload攔截器 --> <interceptor-ref name= "fileupload" > <param name= "allowedtypes" >image/png,image/gif,image/jpeg</param> <param name= "maximumsize" > 20000000 </param> </interceptor-ref> <!-- 配置系統(tǒng)默認(rèn)的攔截器 --> <interceptor-ref name= "defaultstack" /> <result name= "success" >/success.jsp</result> <result name= "input" >/index.jsp</result> |
這樣子,修改配置就可以搞定的事情,比寫一坨代碼真的輕松多了。
配置錯(cuò)誤信息
對(duì)于上傳出現(xiàn)錯(cuò)誤的情況,系統(tǒng)默認(rèn)都是提示英文的錯(cuò)誤信息,但是為了輸出國際化的提示信息,這就需要在國際化的資源配置文件中增加以下兩個(gè)key的消息定義:
-
struts.messages.error.content.type.not.allowed
=上傳文件類型不正確,請(qǐng)重新上傳 -
struts.messages.error.file.too.large
=您上傳的文件太大,請(qǐng)重新上傳
接下來就可以使用<s:fielderror/>來輸出錯(cuò)誤信息了。
文件上傳的常量配置
在文章的開始,我們說到default.properties
中的配置,其中有一個(gè)struts.multipart.savedir
配置,那么該配置項(xiàng)的具體作用是什么呢?
在struts2執(zhí)行文件上傳的過程中,需要指定一個(gè)臨時(shí)文件夾,用來存放上傳過程中產(chǎn)生的臨時(shí)文件;如果沒有指定臨時(shí)文件夾,系統(tǒng)默認(rèn)使用javax.servlet.context.tempdir
,在tomcat安裝路徑下的work/catalina/localhost/路徑下。而這個(gè)struts.multipart.savedir就是配置臨時(shí)文件的存放位置的。所以在開發(fā)的過程中,一定要注意該目錄是否有讀寫權(quán)限哦。
還有一個(gè)struts.multipart.maxsize
配置,該配置表示上傳文件的大小,如果同時(shí)指定了這個(gè)配置和fileupload攔截器的maximumsize屬性,則先和struts.multipart.maxsize
配置的比較,再和fileupload攔截器的maximumsize屬性比較,如果文件大小超過了struts.multipart.maxsize
配置的,則會(huì)出現(xiàn)異常,并不會(huì)將result轉(zhuǎn)到input,這個(gè)一定要注意。
總結(jié)
這篇文章詳細(xì)的總結(jié)了struts2中的文件上傳,內(nèi)容有點(diǎn)多,基本都是手冊(cè)上的內(nèi)容,也罷,就當(dāng)手冊(cè)了。
好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)服務(wù)器之家的支持。
原文鏈接:https://www.jellythink.com/archives/299