1.
???
文件上傳
的原理:
表單元素的
enctype
屬性指定的是表單數據的編碼方式,該屬性有
3
個值:
1)
?????
application/x-www-form-urlencoded
:這是默認編碼方式,它只處理表單域里的
value
屬性值,采用這種編碼方式的表單會將表單域的值處理成
URL
編碼方式。
2)
?????
multipart/form-data
:這種編碼方式的表單會以二進制流的方式來處理表單數據,這種編碼方式會把文件域指定文件的內容也封裝到請求參數里。
3)
?????
text/plain
:這種方式主要適用于直接通過表單發送郵件的方式。
文件上傳
是
web
應用經常用到的一個知識。原理是,通過為表單元素設置
enctype=”multipart/form-data”
屬性,讓表單提交的數據以二進制編碼的方式提交,在接收此請求的
Servlet
中用二進制流來獲取內容,就可以取得上傳文件的內容,從而實現文件的上傳。
在
Java
領域中,有兩個常用的
文件上傳
項目:一個是
Apache
組織
Jakarta
的
Common-FileUpload
組件
(http://commons.apache.org/fileupload/)
,另一個是
Oreilly
組織的
COS
框架
(http://www.servlets.com/cos/)
。利用這兩個框架都能很方便的實現文件的上傳。
2.
???
Struts2
的
文件上傳
:
Struts2
并未提供自己的請求解析器,也就是就
Struts2
不會自己去處理
multipart/form-data
的請求,它需要調用其他請求解析器,將
HTTP
請求中的表單域解析出來。但
Struts2
在原有的上傳解析器基礎上做了進一步封裝,更進一步簡化了
文件上傳
。
Struts2
默認使用的是
Jakarta
的
Common-FileUpload
框架來上傳文件,因此,要在
web
應用中增加兩個
Jar
文件:
commons-fileupload-1.2.jar
和
commons-io-1.3.1.jar
。它在原上傳框架上做了進一步封裝,簡化了
文件上傳
的代碼實現,取消了不同上傳框架上的編程差異。
如果要改成其它的
文件上傳
框架,可以修改
struts.multipart.parser
常量的值為
cos/pell
,默認值是
jakata
。并在
classpath
中增加相應上傳組件的類庫。
2.1.
???
步驟一:創建帶上傳表單域的頁面
????????
????
<%@
page
language
=
"java"
contentType
=
"text/html; charset=UTF-8"
%>
<
html
>
<
head
>
???
<
title
>
Struts2 File Upload
</
title
>
</
head
>
<
body
>
???
<
form
action
=
"fileUpload.action"
method
=
"POST"
enctype
=
"multipart/form-data"
>
???????
文件標題:
<
input
type
=
"text"
name
=
"title"
size
=
"50"
/><
br
/>
???????
選擇文件:
<
input
type
=
"file"
name
=
"upload"
size
=
"50"
/><
br
/>
??????
<
input
type
=
"submit"
value
=
"
上傳
"
/>
???????
???
</
form
>
</
body
>
</
html
>
|
此頁面特殊之處只是把表單的
enctype
屬性設置為
multipart/form-data
。
2.2.
???
步驟二:創建處理上傳請求的
Action
類
????????
????
package
org.qiujy.web.struts2;
import
java.io.BufferedInputStream;
import
java.io.BufferedOutputStream;
import
java.io.File;
import
java.io.FileInputStream;
import
java.io.FileOutputStream;
import
java.io.InputStream;
import
java.io.OutputStream;
import
org.apache.struts2.ServletActionContext;
import
com.opensymphony.xwork2.ActionSupport;
/**
?
*
@author
qiujy
?
*
@version
1.0
?
*/
public
class
FileUploadAction
extends
ActionSupport {
???
private
static
final
int
BUFFER_SIZE
= 16 * 1024;
???
//
文件標題
???
private
String
title
;
???
//
上傳文件域對象
???
private
File
upload
;
???
//
上傳文件名
???
private
String
uploadFileName
;
???
//
上傳文件類型
???
private
String
uploadContentType
;
???
//
保存文件的目錄路徑
(
通過依賴注入
)
???
private
String
savePath
;
???
//
以下省略
getter
和
setter......
???
//
自己封裝的一個把源文件對象復制成目標文件對象
???
private
static
void
copy(File src, File dst) {
??????? InputStream in =
null
;
??????? OutputStream out =
null
;
???????
try
{
??????????? in =
new
BufferedInputStream(
new
FileInputStream(src),
BUFFER_SIZE
);
??????????? out =
new
BufferedOutputStream(
new
FileOutputStream(dst),
???????????????????
BUFFER_SIZE
);
???????????
byte
[] buffer =
new
byte
[
BUFFER_SIZE
];
???????????
int
len = 0;
???????????
while
((len = in.read(buffer)) > 0) {
??????????????? out.write(buffer, 0, len);
??????????? }
??????? }
catch
(Exception e) {
??????????? e.printStackTrace();
??????? }
finally
{
???????????
if
(
null
!= in) {
???????????????
try
{
??????????????????? in.close();
??????????????? }
catch
(IOException e) {
??????????????????? e.printStackTrace();
??????????????? }
??????????? }
???????????
if
(
null
!= out) {
???????????????
try
{
??????????????? ??? out.close();
??????????????? }
catch
(IOException e) {
??????????????????? e.printStackTrace();
??????????????? }
??????????? }
??????? }
??? }
???
@Override
???
public
String execute()
throws
Exception {
???????
//
根據服務器的文件保存地址和原文件名創建目錄文件全路徑
??????? String dstPath = ServletActionContext.
getServletContext
()
??????????????????????????????? .getRealPath(
this
.getSavePath())
??????????????????????????????? +
"\\"
+
this
.getUploadFileName();
???????
??????? System.
out
.println(
"
上傳的文件的類型:
"
+
this
.getUploadContentType());
???????
??????? File dstFile =
new
File(dstPath);
???????
copy
(
this
.
upload
, dstFile);
???????
return
SUCCESS
;
??? }
}
|
上面這個
Action
類中,提供了
title
和
upload
兩個屬性來分別對應頁面的兩個表單域屬性,用來封裝表單域的請求參數。
但是,值得注意的是,此
Action
中還有兩個屬性:
uploadFileName
和
uploadContentType
,這兩個屬性分別用于封裝上傳文件的文件名、文件類型。這是
Struts2
設計的獨到之處:
Strut2
的
Action
類直接通過
File
類型屬性直接封裝了上傳文件的文件內容,但這個
File
屬性無法獲取上傳文件的文件名和文件類型,所以
Struts2
就直接將文件域中包含的上傳文件名和文件類型的信息封裝到
uploadFileName
和
uploadContentType
屬性中,也就是說
Struts2
針對表單中名為
xxx
的文件域,在對應的
Action
類中使用
3
個屬性來封裝該文件域信息
:
l?
類型為
File
的
xxx
屬性:用來封裝頁面文件域對應的文件內容。
l?
類型為
String
的
xxxFileName
屬性:用來封裝該文件域對應的文件的文件名。
l?
類型為
String
的
xxxContentType
屬性:用來封裝該文件域應用的文件的文件類型。
另外,在這個
Action
類中還有一個
savePath
屬性,它的值是通過配置文件來動態設置的,這也是
Strut2
設計中的一個依賴注入特性的使用。
2.3.
???
步驟三:配置
struts.xml
文件:
????????
????
<!
DOCTYPE
struts
PUBLIC
???????
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
???????
"http://struts.apache.org/dtds/struts-2.0.dtd"
>
<
struts
>
???
<
package
name
=
"fileUploadDemo"
extends
=
"struts-default"
>
???????
<
action
name
=
"fileUpload"
class
=
"org.qiujy.web.struts2.FileUploadAction"
>
<!--
動態設置
Action
中的
savePath
屬性的值
-->
???????????
<
param
name
=
"savePath"
>
/upload
</
param
>
???????????
<
result
name
=
"success"
>
/showupload.jsp
</
result
>
???????
</
action
>
???
</
package
>
</
struts
>
|
??????
在這個文件中跟以前配置唯一不同的是給
action
配置了一個
<param …/>
元素,用來為該
Action
的
savePath
屬性動態注入值。
web.xml
中的配置跟以前的應用一樣。說明一點:好多網絡文章說
Struts2
上傳時要在
web.xml
中配置一個名為
ActionContextUp
的過濾器,說是有一些莫名的錯誤,可是是我用了
Struts2
新版本
2.0.9GA
版,測了
n
次,沒出現什么問題,所以沒配置。
2.4.
???
運行調試:
運行前要在根目錄下創建一個名為
upload
的文件夾,用來存放上傳后的文件。
上傳結果:
3.
???
文件類型及錯誤輸出:
在上例中,若要配置上傳的文件只能是一些普通的圖片文件格式:
image/bmp
、
image/png
、
image/gif
、
image/jpeg
、
image/jpg
等,則可在
struts.xml
文件中按如下方式配置:
????????
????
<!
DOCTYPE
struts
PUBLIC
???????
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
???????
"http://struts.apache.org/dtds/struts-2.0.dtd"
>
<
struts
>
???
<
constant
name
=
"struts.custom.i18n.resources"
value
=
"messages"
/>
???
<
package
name
=
"fileUploadDemo"
extends
=
"struts-default"
>
???????
<
action
name
=
"fileUpload"
???????????
class
=
"org.qiujy.web.struts2.FileUploadAction"
>
???????????
<
interceptor-ref
name
=
"fileUpload"
>
?????????????
<!--
配置允許上傳的文件類型,多個用
","
分隔
-->
?????????????
<
param
name
=
"allowedTypes"
>
???
image/bmp,image/png,image/gif,image/jpeg,image/jpg
,image/x-png, image/pjpeg
?????????????
</
param
>
?????????????
<!--
配置允許上傳的文件大小,單位字節
-->
?????????????
<
param
name
=
"maximumSize"
>
102400
</
param
>
??????????
</
interceptor-ref
>
??????????
<
interceptor-ref
name
=
"defaultStack"
/>
???????????
<!--
動態設置
Action
中的
savePath
屬性的值
-->
???????????
<
param
name
=
"savePath"
>
/upload
</
param
>
???????????
<
result
name
=
"input"
>
/index.jsp
</
result
>
???????????
<
result
name
=
"success"
>
/showupload.jsp
</
result
>
???????
</
action
>
???
</
package
>
</
struts
>
|
如果上傳文件失敗,系統返回到
input
對應的頁面,要在
input
對應的頁面輸出文件過濾失敗信息,可以在
input
對應的頁面中增加
<s:fielderror/>
來顯示錯誤信息。
運行調試:
結果:
????????
顯然,這樣的提示不太友好,應用使用國際化信息。在國際化資源文件中添加如下三句:
????????
????
#
更改上傳文件類型不允許的提示信息
struts.messages.error.content.type.not.allowed=
文件上傳
失敗:你要上傳的文件類型不允許
#
更改上傳文件太大的提示信息
struts.messages.error.file.too.large=
文件上傳
失敗:你要上傳的文件太大
#
文件上傳
其它錯誤信息
struts.messages.error.uploading=
文件上傳
失敗:發生內部錯誤
|
????????
別忘了要用
native2ascii.exe
進行編碼轉換哦。再運行調試:
另外,在控制臺會看到一條消息:
????????
????
Unable to find 'struts.multipart.saveDir' property setting. Defaulting to javax.servlet.context.tempdir
Removing file upload D:\tomcat6.0.13\work\Catalina\localhost\fileload_struts2\upload__4b616fd1_115a3d5d9dc__7fff_00000005.tmp
|
第一個說是找不以
struts.multipart.saveDir
,即沒有指定臨時文件夾,這個很好解決,只需指定一個
struts.multipart.saveDir
常量值為某個目錄來解決。第二個說正在刪除一個臨時文件,這個臨時文件是上傳過程中產生的,屬正常。
4.
???
多
文件上傳
:
Struts2
也可以很方便地實現多
文件上傳
。
????????
在輸入表單域增加多個文件域:
multifileupload.jsp
????????
<%@
page
language
=
"java"
contentType
=
"text/html; charset=UTF-8"
%>
<%@
taglib
uri
=
"/struts-tags"
prefix
=
"s"
%>
<
html
>
<
head
>
</
head
>
<
body
>
???
<
font
color
=
"red"
><
s:fielderror
/></
font
>
???
<
form
action
=
"multiFileUpload.action"
method
=
"POST"
enctype
=
"multipart/fo
發表評論
最近訪客 更多訪客>>最新評論
|
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

評論