在做B/S系統時,通常會涉及到上傳文件和下載文件,在沒接struts2框架之前,我們都是使用apache下面的commons子項目的FileUpload組件來進行文件的上傳,但是那樣做的話,代碼看起來比較繁瑣,而且不靈活,在學習了struts2后,struts2為文件上傳下載提供了更好的實現機制,在這里我分別就單文件上傳和多文件上傳的源代碼進行一下講解,這里需要導入文件下載上傳的兩個jar文件,一個是commons-fileupload-1.2.2.jar,另一個是commons-io-2.0.1.jar
struts2單文件上傳:
首先是一個jsp文件上傳頁面,這個比較簡單,就是一個表單,里面有個文件上傳框
1
2
3
4
5
6
7
8
9
|
<!--在進行文件上傳時,表單提交方式一定要是post的方式,因為文件上傳時二進制文件可能會很大,還有就是enctype屬性,這個屬性一定要寫成multipart/form-data, 不然就會以二進制文本上傳到服務器端--> < form action = "fileUpload.action" method = "post" enctype = "multipart/form-data" > username: < input type = "text" name = "username" >< br > file: < input type = "file" name = "file" >< br > < input type = "submit" value = "submit" > </ form > |
接下來是FileUploadAction部分代碼,因為struts2對上傳和下載都提供了很好的實習機制,所以在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
76
77
78
79
80
81
82
|
public class FileUploadAction extends ActionSupport { private String username; //注意,file并不是指前端jsp上傳過來的文件本身,而是文件上傳過來存放在臨時文件夾下面的文件 private File file; //提交過來的file的名字 private String fileFileName; //提交過來的file的MIME類型 private String fileContentType; public String getUsername() { return username; } public void setUsername(String username) { this .username = username; } public File getFile() { return file; } public void setFile(File file) { this .file = file; } public String getFileFileName() { return fileFileName; } public void setFileFileName(String fileFileName) { this .fileFileName = fileFileName; } public String getFileContentType() { return fileContentType; } public void setFileContentType(String fileContentType) { this .fileContentType = fileContentType; } @Override public String execute() throws Exception { String root = ServletActionContext.getServletContext().getRealPath( "/upload" ); InputStream is = new FileInputStream(file); OutputStream os = new FileOutputStream( new File(root, fileFileName)); System.out.println( "fileFileName: " + fileFileName); // 因為file是存放在臨時文件夾的文件,我們可以將其文件名和文件路徑打印出來,看和之前的fileFileName是否相同 System.out.println( "file: " + file.getName()); System.out.println( "file: " + file.getPath()); byte [] buffer = new byte [ 500 ]; int length = 0 ; while (- 1 != (length = is.read(buffer, 0 , buffer.length))) { os.write(buffer); } os.close(); is.close(); return SUCCESS; } } |
首先我們要清楚一點,這里的file并不是真正指代jsp上傳過來的文件,當文件上傳過來時,struts2首先會尋找struts.multipart.saveDir(這個是在default.properties里面有)這個name所指定的存放位置,我們可以新建一個struts.properties屬性文件來指定這個臨時文件存放位置,如果沒有指定,那么文件會存放在tomcat的apache-tomcat-7.0.29\work\Catalina\localhost\目錄下,然后我們可以指定文件上傳后的存放位置,通過輸出流將其寫到流里面就行了,這時我們就可以在文件夾里看到我們上傳的文件了。
文件上傳后我們還需要將其下載下來,其實struts2的文件下載原理很簡單,就是定義一個輸入流,然后將文件寫到輸入流里面就行,關鍵配置還是在struts.xml這個配置文件里配置:
FileDownloadAction代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public class FileDownloadAction extends ActionSupport { public InputStream getDownloadFile() { return ServletActionContext.getServletContext().getResourceAsStream( "upload/通訊錄2012年9月4日.xls" ); } @Override public String execute() throws Exception { return SUCCESS; } } |
我們看,這個action只是定義了一個輸入流,然后為其提供getter方法就行,接下來我們看看struts.xml的配置文件:
1
2
3
4
5
6
|
< action name = "fileDownload" class = "com.xiaoluo.struts2.FileDownloadAction" > < result name = "success" type = "stream" > < param name = "contentDisposition" >attachment;filename="通訊錄2012年9月4日.xls"</ param > < param name = "inputName" >downloadFile</ param > </ result > </ action > |
struts.xml配置文件有幾個地方我們要注意,首先是result的類型,以前我們定義一個action,result那里我們基本上都不寫type屬性,因為其默認是請求轉發(dispatcher)的方式,除了這個屬性一般還有redirect(重定向)等這些值,在這里因為我們用的是文件下載,所以type一定要定義成stream類型,告訴action這是文件下載的result,result元素里面一般還有param子元素,這個是用來設定文件下載時的參數,inputName這個屬性就是得到action中的文件輸入流,名字一定要和action中的輸入流屬性名字相同,然后就是contentDisposition屬性,這個屬性一般用來指定我們希望通過怎么樣的方式來處理下載的文件,如果值是attachment,則會彈出一個下載框,讓用戶選擇是否下載,如果不設定這個值,那么瀏覽器會首先查看自己能否打開下載的文件,如果能,就會直接打開所下載的文件,(這當然不是我們所需要的),另外一個值就是filename這個就是文件在下載時所提示的文件下載名字。在配置完這些信息后,我們就能過實現文件的下載功能了。
struts2多文件上傳:
其實多文件上傳和單文件上傳原理一樣,單文件上傳過去的是單一的File,多文件上傳過去的就是一個List<File>集合或者是一個File[]數組,首先我們來看一下前端jsp部分的代碼,這里我用到了jquery來實現動態的添加文件下載框以及動態的刪除下載框:
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
|
<script type= "text/javascript" src= "script/jquery-1.8.1.js" ></script> <script type= "text/javascript" > $(function() { $( "#button" ).click(function() { var html = $( "<input type='file' name='file'>" ); var button = $( "<input type='button' name='button' value='刪除'><br>" ); $( "#body div" ).append(html).append(button); button.click(function() { html.remove(); button.remove(); }) }) }) </script> </head> <body id= "body" > <form action= "fileUpload2.action" method= "post" enctype= "multipart/form-data" > username: <input type= "text" name= "username" ><br> file: <input type= "file" name= "file" > <input type= "button" value= "添加" id= "button" ><br> <div></div> <input type= "submit" value= "submit" > </form> </body> |
file的名字必須都命名成file才行,然后處理多文件上傳的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
76
77
78
79
80
|
public class FileUploadAction2 extends ActionSupport { private String username; //這里用List來存放上傳過來的文件,file同樣指的是臨時文件夾中的臨時文件,而不是真正上傳過來的文件 private List<File> file; //這個List存放的是文件的名字,和List<File>中的文件相對應 private List<String> fileFileName; private List<String> fileContentType; public String getUsername() { return username; } public void setUsername(String username) { this .username = username; } public List<File> getFile() { return file; } public void setFile(List<File> file) { this .file = file; } public List<String> getFileFileName() { return fileFileName; } public void setFileFileName(List<String> fileFileName) { this .fileFileName = fileFileName; } public List<String> getFileContentType() { return fileContentType; } public void setFileContentType(List<String> fileContentType) { this .fileContentType = fileContentType; } @Override public String execute() throws Exception { String root = ServletActionContext.getServletContext().getRealPath( "/upload" ); for ( int i = 0 ; i < file.size(); i++) { InputStream is = new FileInputStream(file.get(i)); OutputStream os = new FileOutputStream( new File(root, fileFileName.get(i))); byte [] buffer = new byte [ 500 ]; @SuppressWarnings ( "unused" ) int length = 0 ; while (- 1 != (length = is.read(buffer, 0 , buffer.length))) { os.write(buffer); } os.close(); is.close(); } return SUCCESS; } } |
這樣同樣將其寫到一個輸出流里面,這樣我們就可以在文件夾里看到上傳的多個文件了
接下來的文件下載就和剛才的文件下載一模一樣,struts.xml也是一樣的,這里就不再重復了
總結:總的來說,struts2提供的文件上傳下載機制簡化了我們很多代碼,我們可以在以后的項目中使用該機制,同樣我們也可以使用FileUpload組件來進行文件的上傳,這個都是因個人愛好決定!
關于JavaWeb中的文件上傳和下載功能的內容就這么多,謝謝大家的閱讀。