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