web文件上傳采用post的方式,與post提交表單不同的是,上傳文件需要設置form的enctype屬性為multipart/form-data.由于上傳的文件會比較大,因此需要設置該參數指定瀏覽器使用二進制上傳。如果不設置,enctype屬性默認為application/x-www-form-urlencoded,使用瀏覽器將使用ascii向服務器發送數據,導致發送文件失敗。
上傳文件要使用文件域(<input type='file'/>,并把form的enctype設置為multipart/form-data.
客戶端上傳頁面如圖所示:
代碼如下:
upload.html
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
|
<!doctype html public "-//w3c//dtd html 4.01 transitional//en" > <html> <head> <title>上傳文件</title> <meta http-equiv= "keywords" content= "keyword1,keyword2,keyword3" > <meta http-equiv= "description" content= "this is my page" > <meta http-equiv= "content-type" content= "text/html; charset=utf-8" > <link rel= "stylesheet" type= "text/css" href= "css/style.css" > </head> <body> <form action= "servlet/uploadservlet" method= "post" enctype= "multipart/form-data" > <div align= "center" ><br/> <fieldset style= "width:90%" > <legend>上傳文件</legend><br/> <div class = 'line' > <div align= 'left' class = "leftdiv" >上傳文件一</div> <div align= 'left' class = "rightdiv" > <input type= "file" name= "file1" class = "text" > </div> </div> <div class = 'line' > <div align= 'left' class = "leftdiv" >上傳文件二</div> <div align= 'left' class = "rightdiv" > <input type= "file" name= "file2" class = "text" > </div> </div> <div class = 'line' > <div align= 'left' class = "leftdiv" >上傳文件說明一</div> <div align= 'left' class = "rightdiv" ><input type= "text" name= "description1" class = "text" ></div> </div> <div class = 'line' > <div align= 'left' class = "leftdiv" >上傳文件說明二</div> <div align= 'left' class = "rightdiv" ><input type= "text" name= "description2" class = "text" ></div> </div> <div class = 'line' > <div align= 'left' class = "leftdiv" ></div> <div align= 'left' class = "rightdiv" ><br/> <input type= "submit" value= " 上傳文件 " class = "button" > </div> </div> </fieldset> </div> </form> </body> </html> |
客戶端運行的代碼很簡單,服務器要復雜一點。要想獲取其中的內容,必須根據http協議所規定的格式來解析瀏覽器提交的request.
解析二進制流比較麻煩。已經有許多類庫已經完成了這項工作,例如smartupload與apache commons fileupload.smartupload是一個商業類庫,解析request過程中數據存放在內存里,因此速度較快,但上傳較大文件時會發生內存溢出。apache commons fileupload是一個免費的開源的類庫。一些框架比如struts里集成了apache common fileupload類庫來實現文件上傳。
如圖所示:
代碼如下:
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
|
package com.helloweenvsfei.servlet; import java.io.file; import java.io.fileoutputstream; import java.io.ioexception; import java.io.inputstream; import java.io.outputstream; import java.io.printwriter; import java.net.urlencoder; import java.util.list; import javax.servlet.servletexception; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import org.apache.commons.fileupload.diskfileupload; import org.apache.commons.fileupload.fileitem; import org.apache.commons.fileupload.fileuploadexception; public class uploadservlet extends httpservlet { private static final long serialversionuid = 7523024737218332088l; public void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { response.setcharacterencoding( "utf-8" ); response.getwriter().println( "請以 post 方式上傳文件" ); } @suppresswarnings ( "unchecked" ) public void dopost(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { file file1 = null , file2 = null ; string description1 = null , description2 = null ; response.setcharacterencoding( "utf-8" ); response.setcontenttype( "text/html" ); printwriter out = response.getwriter(); out.println( "<!doctype html public \"-//w3c//dtd html 4.01 transitional//en\">" ); out.println( "<html>" ); out.println( " <head><title>a servlet</title></head>" ); out.println( " <link rel='stylesheet' type='text/css' href='../css/style.css'>" ); out.println( " <body>" ); out.println( "<div align=center><br/>" ); out.println( "<fieldset style='width:90%'><legend>上傳文件</legend><br/>" ); out.println( " <div class='line'>" ); out.println( " <div align='left' class='leftdiv'>上傳日志:</div>" ); out.println( " <div align='left' class='rightdiv'>" ); // 使用 diskfileupload 對象解析 request diskfileupload diskfileupload = new diskfileupload(); try { // 將 解析的結果 放置在 list 中 list<fileitem> list = diskfileupload.parserequest(request); out.println( "遍歷所有的 fileitem ... <br/>" ); // 遍歷 list 中所有的 fileitem for (fileitem fileitem : list){ if (fileitem.isformfield()){ // 如果是 文本域 if ( "description1" .equals(fileitem.getfieldname())){ // 如果該 fileitem 名稱為 description1 out.println( "遍歷到 description1 ... <br/>" ); description1 = new string(fileitem.getstring().getbytes(), "utf-8" ); } if ( "description2" .equals(fileitem.getfieldname())){ // 如果該 fileitem 名稱為 description2 out.println( "遍歷到 description2 ... <br/>" ); description2 = new string(fileitem.getstring().getbytes(), "utf-8" ); } } else { // 否則,為文件域 if ( "file1" .equals(fileitem.getfieldname())){ // 客戶端文件路徑構建的 file 對象 file remotefile = new file( new string(fileitem.getname().getbytes(), "utf-8" )); out.println( "遍歷到 file1 ... <br/>" ); out.println( "客戶端文件位置: " + remotefile.getabsolutepath() + "<br/>" ); // 服務器端文件,放在 upload 文件夾下 file1 = new file( this .getservletcontext().getrealpath( "attachment" ), remotefile.getname()); file1.getparentfile().mkdirs(); file1.createnewfile(); // 寫文件,將 fileitem 的文件內容寫到文件中 inputstream ins = fileitem.getinputstream(); outputstream ous = new fileoutputstream(file1); try { byte [] buffer = new byte [ 1024 ]; int len = 0 ; while ((len=ins.read(buffer)) > - 1 ) ous.write(buffer, 0 , len); out.println( "已保存文件" + file1.getabsolutepath() + "<br/>" ); } finally { ous.close(); ins.close(); } } if ( "file2" .equals(fileitem.getfieldname())){ // 客戶端文件路徑構建的 file 對象 file remotefile = new file( new string(fileitem.getname().getbytes(), "utf-8" )); out.println( "遍歷到 file2 ... <br/>" ); out.println( "客戶端文件位置: " + remotefile.getabsolutepath() + "<br/>" ); // 服務器端文件,放在 upload 文件夾下 file2 = new file( this .getservletcontext().getrealpath( "attachment" ), remotefile.getname()); file2.getparentfile().mkdirs(); file2.createnewfile(); // 寫文件,將 fileitem 的文件內容寫到文件中 inputstream ins = fileitem.getinputstream(); outputstream ous = new fileoutputstream(file2); try { byte [] buffer = new byte [ 1024 ]; int len = 0 ; while ((len=ins.read(buffer)) > - 1 ) ous.write(buffer, 0 , len); out.println( "已保存文件" + file2.getabsolutepath() + "<br/>" ); } finally { ous.close(); ins.close(); } } } } out.println( "request 解析完畢" ); } catch (fileuploadexception e) { // todo auto-generated catch block e.printstacktrace(); } out.println( " </div>" ); out.println( " </div>" ); if (file1 != null ){ out.println( " <div class='line'>" ); out.println( " <div align='left' class='leftdiv'>file1:</div>" ); out.println( " <div align='left' class='rightdiv'>" ); out.println( " <a href='" + request.getcontextpath() + "/attachment/" + file1.getname() + "' target=_blank>" + file1.getname() + "</a>" ); out.println( " </div>" ); out.println( " </div>" ); } if (file2 != null ){ out.println( " <div class='line'>" ); out.println( " <div align='left' class='leftdiv'>file2:</div>" ); out.println( " <div align='left' class='rightdiv'>" ); out.println( " <a href='" + request.getcontextpath() + "/attachment/" + urlencoder.encode(file2.getname(), "utf-8" ) + "' target=_blank>" + file2.getname() + "</a>" ); out.println( " </div>" ); out.println( " </div>" ); } out.println( " <div class='line'>" ); out.println( " <div align='left' class='leftdiv'>description1:</div>" ); out.println( " <div align='left' class='rightdiv'>" ); out.println(description1); out.println( " </div>" ); out.println( " </div>" ); out.println( " <div class='line'>" ); out.println( " <div align='left' class='leftdiv'>description2:</div>" ); out.println( " <div align='left' class='rightdiv'>" ); out.println(description2); out.println( " </div>" ); out.println( " </div>" ); out.println( "</fieldset></div>" ); out.println( " </body>" ); out.println( "</html>" ); out.flush(); out.close(); } } |
程序運行效果如圖所示:
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://blog.csdn.net/wuruiaoxue/article/details/50631498