- 浏览: 10910 次
- 性别:
- 来自: 广州
最新评论
通过ServletRequest类的getInputStream()方法获得一个客户端向服务器发出的数据流、分析上传的文件格式,根据分析结果将多个文件依次输出服务器端的目标文件中。
格式类似下面:
//文件分隔符
-----------------------------7d226137250336
//文件信息头
Content-Disposition: form-data; name="FILE1"; filename="C:\Documents and Settings\Administrator.TIMBER-4O6B0ZZ0\My Documents\tt.sql"
Content-Type: text/plain
//源文件内容
create table info(
content image null);
//下一个文件的分隔符
-----------------------------7d226137250336
Content-Disposition: form-data; name="FILE2"; filename=""
Content-Type: application/octet-stream
-----------------------------7d226137250336
每个表单提交的元素都有分隔符将其分隔,其提交的表单元素的名称和对应的输入值之间也有特殊的字符将其分隔开。
都知道格式了,呵呵就尝试了一下,参照了pell中的MultipartRequest类写了一个上传组件(本来不想自己写的,想改造改造就完事的,可惜反编译出来的代码比较难读),代码如下:
1/**//*
2 * 只支持在windows下上传文件
3 * Created on 2005-10-10
4 *
5 * TODO To change the template for this generated file go to
6 * Window - Preferences - Java - Code Style - Code Templates
7 */
8package study.http.upload;
9
10import java.io.BufferedInputStream;
11import java.io.File;
12import java.io.FileNotFoundException;
13import java.io.FileOutputStream;
14import java.io.IOException;
15import java.io.InputStream;
16import java.io.UnsupportedEncodingException;
17import java.util.ArrayList;
18import java.util.Hashtable;
19import java.util.Iterator;
20import java.util.List;
21import java.util.Map;
22import java.util.Set;
23
24import javax.servlet.ServletException;
25import javax.servlet.ServletInputStream;
26import javax.servlet.http.HttpServlet;
27import javax.servlet.http.HttpServletRequest;
28import javax.servlet.http.HttpServletResponse;
29
30/** *//**
31 * @author liusuifeng
32 *
33 * TODO To change the template for this generated type comment go to Window -
34 * Preferences - Java - Code Style - Code Templates
35 */
36public class TestServlet extends HttpServlet {
37
38 public final static String DEFAULT_ENCODING = "ISO8859_1";
39
40 public final static String CHINESE_ENCODING = "GBK";
41
42 public final static String SIGN_BOUNDARY = "boundary=";
43
44 public final static String SIGN_FORMELEMENT = "name=";
45
46 public final static String SIGN_FORMFILE = "filename=";
47
48 public final static String SIGN_NOTFILE = "application/octet-stream";
49
50 public final static String SIGN_MULTIDATA = "multipart/form-data";
51
52 public final static String CHINESE_CONTENTTYPE = "text/html; charset=GBK";
53
54 private Hashtable paratable = new Hashtable();
55
56 private Hashtable filetable = new Hashtable();
57
58 private String strBoundary = "";
59
60 private String strSavePath="";
61
62
63 private static void println(String s) {
64 System.out.println(s);
65 }
66
67
68
69
70 /** *//**
71 * 增加数据到对应的Hashtable中
72 * 说明:如果Hashtable中已存在该键值,则将新增加的和原来的都封装到列表中。
73 * @param table
74 * @param paraName
75 * @param paraValue
76 */
77 private static void addElement(Hashtable table, String paraName,
78 Object paraValue) {
79 ArrayList list = new ArrayList();
80 if (table.containsKey(paraName)) {
81 Object o = table.get(paraName);
82 if (o instanceof List) {
83 ((List) o).add(paraValue);
84 } else {
85 list.add(o);
86 list.add(paraValue);
87 o = list;
88 }
89 table.put(paraName, o);
90 } else {
91 table.put(paraName, paraValue);
92 }
93 }
94
95 public static String getHashInfo(Hashtable paratable){
96 StringBuffer sb=new StringBuffer();
97 Set keySet=paratable.keySet();
98 Iterator it=keySet.iterator();
99 while(it.hasNext()){
100
101 Object keyobj=it.next();
102 Object valueobj=paratable.get(keyobj);
103
104 sb.append("<tr>");
105 sb.append("<td>"+keyobj.toString()+"</td>");
106 if(valueobj instanceof List){
107 sb.append("<td>");
108 int isize=((List)valueobj).size();
109 for(int i=0;i<isize;i++){
110 Object tempobj=((List)valueobj).get(i);
111 if(i<isize-1){
112 sb.append(tempobj.toString()+",");
113 }
114 else{
115 sb.append(tempobj.toString());
116 }
117 }
118
119 sb.append("</td>");
120 }
121 else{
122 sb.append("<td>"+valueobj.toString()+"</td>");
123 }
124 sb.append("</tr>");
125 }
126 return sb.toString();
127 }
128
129
130 private static byte[] getfileBytes(InputStream is) {
131 List byteList = new ArrayList();
132 byte[] filebyte = null;
133 int readbyte = 0;
134 try {
135 while ((readbyte = is.read()) != -1) {
136 byteList.add(new Byte((byte) readbyte));
137 }
138 } catch (FileNotFoundException e) {
139 e.printStackTrace();
140 } catch (IOException e) {
141 e.printStackTrace();
142 }
143 filebyte = new byte[byteList.size()];
144 for (int i = 0; i < byteList.size(); i++) {
145 filebyte[i] = ((Byte) byteList.get(i)).byteValue();
146 }
147 return filebyte;
148
149 }
150
151
152
153
154 protected void doGet(HttpServletRequest request,
155 HttpServletResponse response) throws ServletException, IOException {
156 doPost(request, response);
157 }
158
159 protected void doPost(HttpServletRequest request,
160 HttpServletResponse response) throws ServletException, IOException {
161 paratable = new Hashtable();
162 filetable = new Hashtable();
163 strSavePath=this.getInitParameter("savepath");
164 File file=new File(strSavePath);
165 if(!file.exists()){
166 file.mkdirs();
167 }
168 String contentType = request.getContentType();
169 strBoundary = getBoundary(contentType);
170 ServletInputStream sis = request.getInputStream();
171 BufferedInputStream bis = new BufferedInputStream(sis);
172 parseInputStream(bis);
173 appendPara(request.getParameterMap()); /**//*追加url对应传递的参数*/
174 response.setContentType(CHINESE_CONTENTTYPE);
175
176// response.getWriter().write(getOutPutInfo());
177// response.getWriter().write(new String(getfileBytes(sis),"GBK"));
178 bis.close();
179 sis.close();
180 request.setAttribute("para",paratable);
181 request.setAttribute("file",filetable);
182
183 this.getServletContext().getRequestDispatcher("/result.jsp").
184 forward(request,response);
185
186 }
187
188
189 /** *//**
190 * 不用Hashtable对应的put方法,目的避免覆盖重复的键值
191 * @return
192 */
193 private void appendPara(Map map){
194
195 if(map!=null){
196 Set keySet=map.keySet();
197 Iterator it=keySet.iterator();
198 while(it.hasNext()){
199 Object keyobj=it.next();
200 String[] valueobj=(String[])map.get(keyobj);
201 println("keyobj===="+keyobj);
202 println("valueobj===="+valueobj);
203 for(int i=0;i<valueobj.length;i++){
204 addElement(paratable,(String)keyobj,valueobj[i]);
205 }
206 }
207 }
208 }
209
210
211
212 /** *//**
213 * 输出上传表单信息
214 *
215 * @param pw
216 */
217 protected String getOutPutInfo() {
218 StringBuffer sb = new StringBuffer();
219 sb.append("<table width=100% border=1>");
220 sb.append("<tr><td>参数名</td><td>参数值</td></tr>");
221 sb.append(getHashInfo(paratable));
222 sb.append(getHashInfo(filetable));
223 sb.append("</table>");
224 return sb.toString();
225 }
226
227 /** *//**
228 * 解析字节流
229 * @param is
230 */
231 private void parseInputStream(InputStream is) {
232 byte[] sizes = getfileBytes(is);
233 int icount = 0;
234 String s = "";
235 int readbyte = 0;
236 String reals;
237 try {
238 reals = new String(sizes, DEFAULT_ENCODING);
239 String realsvalue = new String(sizes, CHINESE_ENCODING);
240 String[] arrs = reals.split(strBoundary);
241 String[] arrsvalue = realsvalue.split(strBoundary);
242 for (int i = 0; i < arrs.length; i++) {
243 String tempStr = arrs[i];
244 String tempStr2 = arrsvalue[i];
245 if (tempStr.indexOf(SIGN_FORMFILE) >= 0) {
246 readFile(tempStr, tempStr2);
247 } else {
248 readParameter(tempStr2);
249 }
250 }
251 } catch (UnsupportedEncodingException e) {
252 e.printStackTrace();
253 }
254
255 }
256
257 /** *//**
258 * 获取本次上传对应的表单元素间的分隔符,注意该分隔符是随机生成的
259 * @param contentType
260 * @return
261 */
262 private String getBoundary(String contentType) {
263 String tempStr = "";
264 if (contentType != null && contentType.startsWith(SIGN_MULTIDATA)
265 && contentType.indexOf(SIGN_BOUNDARY) != -1) {
266 //获取表单每个元素的分隔符
267 tempStr = contentType
268 .substring(
269 contentType.indexOf(SIGN_BOUNDARY)
270 + SIGN_BOUNDARY.length()).trim();
271 }
272 return tempStr;
273 }
274
275 /** *//**
276 * 解析文件上传对应的字节流。实现算法<br>
277 * 通过解析ISO8859_1编码方式的字符串后转换成对应上传文件的字节。
278 * 通过解析GBK编码方式的字符串后转换成对应上传文件的文件名。
279 * 说明:因不清楚字节在不同编码方式下的关系,只好使用两个字符串(比较影响性能,以后优化)
280 * @param s 以ISO8859_1编码方式组成的字符串
281 * @param s2 以GBK编码方式组成的字符串
282 */
283 private void readFile(String s, String s2) {
284 int filepos = -1;
285 if ((filepos = s.indexOf(SIGN_FORMFILE)) >= 0) {
286 String realName = readFileName(s2);
287 //部分确定上传的是文件而不是任意输入的字符串
288 if(!realName.equals("")&& realName.length()>0 && (realName.indexOf(".")>=0)){
289 String filepath = readWriteFile(s, realName);
290 addElement(filetable, realName, filepath);
291 }
292 }
293 else {
294 /**//*上传的不是文件*/
295 if (s.indexOf(SIGN_NOTFILE) >= 0) {
296 return;
297 }
298 }
299
300 }
301
302 /** *//**
303 * 解析文件上传对应的名称
304 * 实现说明:如果上传的是文件对应格式为:<br>filename="文件名"</br> 格式
305 * 通过处理可以拆分出对应的文件名
306 * @param s 以GBK编码方式组成的包含文件名的字符串
307 * @return 对应上传文件的文件名(不包括文件路径)
308 */
309 private String readFileName(String s) {
310 int filepos = s.indexOf(SIGN_FORMFILE);
311 String tempstr = s.substring(filepos + SIGN_FORMFILE.length() + 1);
312 int iendpos = tempstr.indexOf("\"");
313 String fileName = tempstr.substring(0, iendpos);
314 int ifilenamepos = fileName.lastIndexOf("\\");
315 String realName = fileName.substring(ifilenamepos + 1);
316 return realName;
317
318 }
319
320 /** *//**
321 * 通过解析ISO8859_1编码方式的字符串后转换成对应上传文件的字节。
322 * 实现算法说明:文件名转化后的字节和具体的文件字节中间是以两个重复的两个字符隔开,
323 * 对应char值为13,10,转换后的字符对应的最后四个字符也是格式字符,获取对应中间的字节即为
324 * 上传文件的真正的字节数
325 * @param s 以ISO8859_1编码方式组成的包含文件名和具体文件字节的字符串
326 * @param realName 对应的文件名
327 * @return 对应生成的文件名包括全路径
328 */
329 private String readWriteFile(String s, String realName) {
330 int filepos = s.indexOf(SIGN_FORMFILE);
331 String tempstr = s.substring(filepos + SIGN_FORMFILE.length() + 1);
332 int icount = 0;
333 while (true) {
334 int charnum = tempstr.charAt(icount);
335 int charnum2 = tempstr.charAt(icount + 1);
336 int charnum3 = tempstr.charAt(icount + 2);
337 int charnum4 = tempstr.charAt(icount + 3);
338 if (charnum == 13 && charnum2 == 10 && charnum3 == 13
339 && charnum4 == 10) {
340 break;
341 }
342 icount++;
343 }
344 String filevalue = tempstr.substring(icount + 4, tempstr.length() - 4);
345 FileOutputStream fos = null;
346 String createName=strSavePath + realName;
347 File uploadfile = new File(createName);
348 String shortname=realName.substring(0,realName.lastIndexOf("."));
349 String filetype=realName.substring(realName.lastIndexOf(".")+1);
350 int namecount=1;
351 while(uploadfile.exists()){
352 createName=strSavePath+shortname+"["+namecount+"]"+"."+filetype;
353 uploadfile=new File(createName);
354 namecount++;
355
356 }
357 try {
358 byte[] filebytes = filevalue.getBytes(DEFAULT_ENCODING);
359 fos = new FileOutputStream(uploadfile);
360 fos.write(filebytes);
361 } catch (FileNotFoundException e) {
362 e.printStackTrace();
363 } catch (IOException e1) {
364
365 e1.printStackTrace();
366 } finally {
367 try {
368 fos.close();
369 } catch (IOException e2) {
370
371 e2.printStackTrace();
372 }
373 }
374
375 return createName;
376 }
377
378
379 /** *//**
380 * 解析提交过来的表单元素对应的名称以及值<br>
381 * 实现说明:如果表单元素的是对应格式为:<br>name="表单元素名"</br> 格式
382 * 表单元素名和具体的输入值中间是以两个重复的两个字符隔开,
383 * 对应char值为13,10,转换后的字符对应的最后四个字符也是格式字符,获取对应中间的字符即为
384 * 表单元素的输入值
385 * 通过处理可以拆分出对应的表单元素名以及输入值
386 * @param s 以GBK编码方式组成的包含表单元素名和值的字符串
387 */
388 private void readParameter(String s) {
389 String paraName = "";
390 String paraValue = "";
391 int istartlen = -1;
392 int iendlen = -1;
393
394 if ((istartlen = s.indexOf(SIGN_FORMELEMENT)) >= 0) {
395 String tempstr = s.substring(istartlen + SIGN_FORMELEMENT.length()
396 + 1);
397 int nameindex = tempstr.indexOf("\"");
398 paraName = tempstr.substring(0, nameindex);
399 paraValue = tempstr.substring(nameindex + 5, tempstr.length() - 4);
400 addElement(paratable, paraName, paraValue);
401 }
402 }
403
404}
组件简单说明:
上传路径在servlet初始参数中设定。
上传的表单元素、文件数据分别封装在Hashtable中。
做了测试,测试环境说明:
AppServer: WeblogicSP4
OS: WindowXP/ Soloaris 9.0
测试程序:
index.jsp(文件上传页面):
<html>
<head><title>File Upload</title></head>
<body>
<form name="kkkkkk" action="test.upload?ssss=bbbbbbbbb&ccccc=eeeeeeee" enctype="multipart/form-data" method="post" >
<input type=text name="ssss" ><br>
<input type=text name="ssss" ><br>
<input type=text name="ssss3" ><br>
<textarea name="araea"></textarea><br>
<input type=file name="cccc" ><br>
<input type=file name="ddddd" ><br>
<input type=submit value="submit" name="bbbbbbbbb">
</form>
</body>
</html>
result.jsp(查看提交表单数据)
<%@ page contentType="text/html;charset=GBK"%>
<%@ page import="java.util.*"%>
<%@ page import="study.http.upload.*"%>
<%
Hashtable paratable=(Hashtable)request.getAttribute("para");
Hashtable filetable=(Hashtable)request.getAttribute("file");
String parastr=TestServlet.getHashInfo(paratable);
out.println("<table width=100% border=1>");
out.println(parastr);
out.println(TestServlet.getHashInfo(filetable));
out.println("</table>");
%>
<html>
<head><title>File Upload</title></head>
<body>
</body>
</html>
测试时对应的web应用已经指定相关字符集,weblogic.xml内容如下:
<weblogic-web-app>
<charset-params>
<input-charset>
<resource-path>/*</resource-path>
<java-charset-name>GBK</java-charset-name>
</input-charset>
</charset-params>
</weblogic-web-app>
测试运行基本正常,总算解决了心中的一个很长时间的困惑。
格式类似下面:
//文件分隔符
-----------------------------7d226137250336
//文件信息头
Content-Disposition: form-data; name="FILE1"; filename="C:\Documents and Settings\Administrator.TIMBER-4O6B0ZZ0\My Documents\tt.sql"
Content-Type: text/plain
//源文件内容
create table info(
content image null);
//下一个文件的分隔符
-----------------------------7d226137250336
Content-Disposition: form-data; name="FILE2"; filename=""
Content-Type: application/octet-stream
-----------------------------7d226137250336
每个表单提交的元素都有分隔符将其分隔,其提交的表单元素的名称和对应的输入值之间也有特殊的字符将其分隔开。
都知道格式了,呵呵就尝试了一下,参照了pell中的MultipartRequest类写了一个上传组件(本来不想自己写的,想改造改造就完事的,可惜反编译出来的代码比较难读),代码如下:
1/**//*
2 * 只支持在windows下上传文件
3 * Created on 2005-10-10
4 *
5 * TODO To change the template for this generated file go to
6 * Window - Preferences - Java - Code Style - Code Templates
7 */
8package study.http.upload;
9
10import java.io.BufferedInputStream;
11import java.io.File;
12import java.io.FileNotFoundException;
13import java.io.FileOutputStream;
14import java.io.IOException;
15import java.io.InputStream;
16import java.io.UnsupportedEncodingException;
17import java.util.ArrayList;
18import java.util.Hashtable;
19import java.util.Iterator;
20import java.util.List;
21import java.util.Map;
22import java.util.Set;
23
24import javax.servlet.ServletException;
25import javax.servlet.ServletInputStream;
26import javax.servlet.http.HttpServlet;
27import javax.servlet.http.HttpServletRequest;
28import javax.servlet.http.HttpServletResponse;
29
30/** *//**
31 * @author liusuifeng
32 *
33 * TODO To change the template for this generated type comment go to Window -
34 * Preferences - Java - Code Style - Code Templates
35 */
36public class TestServlet extends HttpServlet {
37
38 public final static String DEFAULT_ENCODING = "ISO8859_1";
39
40 public final static String CHINESE_ENCODING = "GBK";
41
42 public final static String SIGN_BOUNDARY = "boundary=";
43
44 public final static String SIGN_FORMELEMENT = "name=";
45
46 public final static String SIGN_FORMFILE = "filename=";
47
48 public final static String SIGN_NOTFILE = "application/octet-stream";
49
50 public final static String SIGN_MULTIDATA = "multipart/form-data";
51
52 public final static String CHINESE_CONTENTTYPE = "text/html; charset=GBK";
53
54 private Hashtable paratable = new Hashtable();
55
56 private Hashtable filetable = new Hashtable();
57
58 private String strBoundary = "";
59
60 private String strSavePath="";
61
62
63 private static void println(String s) {
64 System.out.println(s);
65 }
66
67
68
69
70 /** *//**
71 * 增加数据到对应的Hashtable中
72 * 说明:如果Hashtable中已存在该键值,则将新增加的和原来的都封装到列表中。
73 * @param table
74 * @param paraName
75 * @param paraValue
76 */
77 private static void addElement(Hashtable table, String paraName,
78 Object paraValue) {
79 ArrayList list = new ArrayList();
80 if (table.containsKey(paraName)) {
81 Object o = table.get(paraName);
82 if (o instanceof List) {
83 ((List) o).add(paraValue);
84 } else {
85 list.add(o);
86 list.add(paraValue);
87 o = list;
88 }
89 table.put(paraName, o);
90 } else {
91 table.put(paraName, paraValue);
92 }
93 }
94
95 public static String getHashInfo(Hashtable paratable){
96 StringBuffer sb=new StringBuffer();
97 Set keySet=paratable.keySet();
98 Iterator it=keySet.iterator();
99 while(it.hasNext()){
100
101 Object keyobj=it.next();
102 Object valueobj=paratable.get(keyobj);
103
104 sb.append("<tr>");
105 sb.append("<td>"+keyobj.toString()+"</td>");
106 if(valueobj instanceof List){
107 sb.append("<td>");
108 int isize=((List)valueobj).size();
109 for(int i=0;i<isize;i++){
110 Object tempobj=((List)valueobj).get(i);
111 if(i<isize-1){
112 sb.append(tempobj.toString()+",");
113 }
114 else{
115 sb.append(tempobj.toString());
116 }
117 }
118
119 sb.append("</td>");
120 }
121 else{
122 sb.append("<td>"+valueobj.toString()+"</td>");
123 }
124 sb.append("</tr>");
125 }
126 return sb.toString();
127 }
128
129
130 private static byte[] getfileBytes(InputStream is) {
131 List byteList = new ArrayList();
132 byte[] filebyte = null;
133 int readbyte = 0;
134 try {
135 while ((readbyte = is.read()) != -1) {
136 byteList.add(new Byte((byte) readbyte));
137 }
138 } catch (FileNotFoundException e) {
139 e.printStackTrace();
140 } catch (IOException e) {
141 e.printStackTrace();
142 }
143 filebyte = new byte[byteList.size()];
144 for (int i = 0; i < byteList.size(); i++) {
145 filebyte[i] = ((Byte) byteList.get(i)).byteValue();
146 }
147 return filebyte;
148
149 }
150
151
152
153
154 protected void doGet(HttpServletRequest request,
155 HttpServletResponse response) throws ServletException, IOException {
156 doPost(request, response);
157 }
158
159 protected void doPost(HttpServletRequest request,
160 HttpServletResponse response) throws ServletException, IOException {
161 paratable = new Hashtable();
162 filetable = new Hashtable();
163 strSavePath=this.getInitParameter("savepath");
164 File file=new File(strSavePath);
165 if(!file.exists()){
166 file.mkdirs();
167 }
168 String contentType = request.getContentType();
169 strBoundary = getBoundary(contentType);
170 ServletInputStream sis = request.getInputStream();
171 BufferedInputStream bis = new BufferedInputStream(sis);
172 parseInputStream(bis);
173 appendPara(request.getParameterMap()); /**//*追加url对应传递的参数*/
174 response.setContentType(CHINESE_CONTENTTYPE);
175
176// response.getWriter().write(getOutPutInfo());
177// response.getWriter().write(new String(getfileBytes(sis),"GBK"));
178 bis.close();
179 sis.close();
180 request.setAttribute("para",paratable);
181 request.setAttribute("file",filetable);
182
183 this.getServletContext().getRequestDispatcher("/result.jsp").
184 forward(request,response);
185
186 }
187
188
189 /** *//**
190 * 不用Hashtable对应的put方法,目的避免覆盖重复的键值
191 * @return
192 */
193 private void appendPara(Map map){
194
195 if(map!=null){
196 Set keySet=map.keySet();
197 Iterator it=keySet.iterator();
198 while(it.hasNext()){
199 Object keyobj=it.next();
200 String[] valueobj=(String[])map.get(keyobj);
201 println("keyobj===="+keyobj);
202 println("valueobj===="+valueobj);
203 for(int i=0;i<valueobj.length;i++){
204 addElement(paratable,(String)keyobj,valueobj[i]);
205 }
206 }
207 }
208 }
209
210
211
212 /** *//**
213 * 输出上传表单信息
214 *
215 * @param pw
216 */
217 protected String getOutPutInfo() {
218 StringBuffer sb = new StringBuffer();
219 sb.append("<table width=100% border=1>");
220 sb.append("<tr><td>参数名</td><td>参数值</td></tr>");
221 sb.append(getHashInfo(paratable));
222 sb.append(getHashInfo(filetable));
223 sb.append("</table>");
224 return sb.toString();
225 }
226
227 /** *//**
228 * 解析字节流
229 * @param is
230 */
231 private void parseInputStream(InputStream is) {
232 byte[] sizes = getfileBytes(is);
233 int icount = 0;
234 String s = "";
235 int readbyte = 0;
236 String reals;
237 try {
238 reals = new String(sizes, DEFAULT_ENCODING);
239 String realsvalue = new String(sizes, CHINESE_ENCODING);
240 String[] arrs = reals.split(strBoundary);
241 String[] arrsvalue = realsvalue.split(strBoundary);
242 for (int i = 0; i < arrs.length; i++) {
243 String tempStr = arrs[i];
244 String tempStr2 = arrsvalue[i];
245 if (tempStr.indexOf(SIGN_FORMFILE) >= 0) {
246 readFile(tempStr, tempStr2);
247 } else {
248 readParameter(tempStr2);
249 }
250 }
251 } catch (UnsupportedEncodingException e) {
252 e.printStackTrace();
253 }
254
255 }
256
257 /** *//**
258 * 获取本次上传对应的表单元素间的分隔符,注意该分隔符是随机生成的
259 * @param contentType
260 * @return
261 */
262 private String getBoundary(String contentType) {
263 String tempStr = "";
264 if (contentType != null && contentType.startsWith(SIGN_MULTIDATA)
265 && contentType.indexOf(SIGN_BOUNDARY) != -1) {
266 //获取表单每个元素的分隔符
267 tempStr = contentType
268 .substring(
269 contentType.indexOf(SIGN_BOUNDARY)
270 + SIGN_BOUNDARY.length()).trim();
271 }
272 return tempStr;
273 }
274
275 /** *//**
276 * 解析文件上传对应的字节流。实现算法<br>
277 * 通过解析ISO8859_1编码方式的字符串后转换成对应上传文件的字节。
278 * 通过解析GBK编码方式的字符串后转换成对应上传文件的文件名。
279 * 说明:因不清楚字节在不同编码方式下的关系,只好使用两个字符串(比较影响性能,以后优化)
280 * @param s 以ISO8859_1编码方式组成的字符串
281 * @param s2 以GBK编码方式组成的字符串
282 */
283 private void readFile(String s, String s2) {
284 int filepos = -1;
285 if ((filepos = s.indexOf(SIGN_FORMFILE)) >= 0) {
286 String realName = readFileName(s2);
287 //部分确定上传的是文件而不是任意输入的字符串
288 if(!realName.equals("")&& realName.length()>0 && (realName.indexOf(".")>=0)){
289 String filepath = readWriteFile(s, realName);
290 addElement(filetable, realName, filepath);
291 }
292 }
293 else {
294 /**//*上传的不是文件*/
295 if (s.indexOf(SIGN_NOTFILE) >= 0) {
296 return;
297 }
298 }
299
300 }
301
302 /** *//**
303 * 解析文件上传对应的名称
304 * 实现说明:如果上传的是文件对应格式为:<br>filename="文件名"</br> 格式
305 * 通过处理可以拆分出对应的文件名
306 * @param s 以GBK编码方式组成的包含文件名的字符串
307 * @return 对应上传文件的文件名(不包括文件路径)
308 */
309 private String readFileName(String s) {
310 int filepos = s.indexOf(SIGN_FORMFILE);
311 String tempstr = s.substring(filepos + SIGN_FORMFILE.length() + 1);
312 int iendpos = tempstr.indexOf("\"");
313 String fileName = tempstr.substring(0, iendpos);
314 int ifilenamepos = fileName.lastIndexOf("\\");
315 String realName = fileName.substring(ifilenamepos + 1);
316 return realName;
317
318 }
319
320 /** *//**
321 * 通过解析ISO8859_1编码方式的字符串后转换成对应上传文件的字节。
322 * 实现算法说明:文件名转化后的字节和具体的文件字节中间是以两个重复的两个字符隔开,
323 * 对应char值为13,10,转换后的字符对应的最后四个字符也是格式字符,获取对应中间的字节即为
324 * 上传文件的真正的字节数
325 * @param s 以ISO8859_1编码方式组成的包含文件名和具体文件字节的字符串
326 * @param realName 对应的文件名
327 * @return 对应生成的文件名包括全路径
328 */
329 private String readWriteFile(String s, String realName) {
330 int filepos = s.indexOf(SIGN_FORMFILE);
331 String tempstr = s.substring(filepos + SIGN_FORMFILE.length() + 1);
332 int icount = 0;
333 while (true) {
334 int charnum = tempstr.charAt(icount);
335 int charnum2 = tempstr.charAt(icount + 1);
336 int charnum3 = tempstr.charAt(icount + 2);
337 int charnum4 = tempstr.charAt(icount + 3);
338 if (charnum == 13 && charnum2 == 10 && charnum3 == 13
339 && charnum4 == 10) {
340 break;
341 }
342 icount++;
343 }
344 String filevalue = tempstr.substring(icount + 4, tempstr.length() - 4);
345 FileOutputStream fos = null;
346 String createName=strSavePath + realName;
347 File uploadfile = new File(createName);
348 String shortname=realName.substring(0,realName.lastIndexOf("."));
349 String filetype=realName.substring(realName.lastIndexOf(".")+1);
350 int namecount=1;
351 while(uploadfile.exists()){
352 createName=strSavePath+shortname+"["+namecount+"]"+"."+filetype;
353 uploadfile=new File(createName);
354 namecount++;
355
356 }
357 try {
358 byte[] filebytes = filevalue.getBytes(DEFAULT_ENCODING);
359 fos = new FileOutputStream(uploadfile);
360 fos.write(filebytes);
361 } catch (FileNotFoundException e) {
362 e.printStackTrace();
363 } catch (IOException e1) {
364
365 e1.printStackTrace();
366 } finally {
367 try {
368 fos.close();
369 } catch (IOException e2) {
370
371 e2.printStackTrace();
372 }
373 }
374
375 return createName;
376 }
377
378
379 /** *//**
380 * 解析提交过来的表单元素对应的名称以及值<br>
381 * 实现说明:如果表单元素的是对应格式为:<br>name="表单元素名"</br> 格式
382 * 表单元素名和具体的输入值中间是以两个重复的两个字符隔开,
383 * 对应char值为13,10,转换后的字符对应的最后四个字符也是格式字符,获取对应中间的字符即为
384 * 表单元素的输入值
385 * 通过处理可以拆分出对应的表单元素名以及输入值
386 * @param s 以GBK编码方式组成的包含表单元素名和值的字符串
387 */
388 private void readParameter(String s) {
389 String paraName = "";
390 String paraValue = "";
391 int istartlen = -1;
392 int iendlen = -1;
393
394 if ((istartlen = s.indexOf(SIGN_FORMELEMENT)) >= 0) {
395 String tempstr = s.substring(istartlen + SIGN_FORMELEMENT.length()
396 + 1);
397 int nameindex = tempstr.indexOf("\"");
398 paraName = tempstr.substring(0, nameindex);
399 paraValue = tempstr.substring(nameindex + 5, tempstr.length() - 4);
400 addElement(paratable, paraName, paraValue);
401 }
402 }
403
404}
组件简单说明:
上传路径在servlet初始参数中设定。
上传的表单元素、文件数据分别封装在Hashtable中。
做了测试,测试环境说明:
AppServer: WeblogicSP4
OS: WindowXP/ Soloaris 9.0
测试程序:
index.jsp(文件上传页面):
<html>
<head><title>File Upload</title></head>
<body>
<form name="kkkkkk" action="test.upload?ssss=bbbbbbbbb&ccccc=eeeeeeee" enctype="multipart/form-data" method="post" >
<input type=text name="ssss" ><br>
<input type=text name="ssss" ><br>
<input type=text name="ssss3" ><br>
<textarea name="araea"></textarea><br>
<input type=file name="cccc" ><br>
<input type=file name="ddddd" ><br>
<input type=submit value="submit" name="bbbbbbbbb">
</form>
</body>
</html>
result.jsp(查看提交表单数据)
<%@ page contentType="text/html;charset=GBK"%>
<%@ page import="java.util.*"%>
<%@ page import="study.http.upload.*"%>
<%
Hashtable paratable=(Hashtable)request.getAttribute("para");
Hashtable filetable=(Hashtable)request.getAttribute("file");
String parastr=TestServlet.getHashInfo(paratable);
out.println("<table width=100% border=1>");
out.println(parastr);
out.println(TestServlet.getHashInfo(filetable));
out.println("</table>");
%>
<html>
<head><title>File Upload</title></head>
<body>
</body>
</html>
测试时对应的web应用已经指定相关字符集,weblogic.xml内容如下:
<weblogic-web-app>
<charset-params>
<input-charset>
<resource-path>/*</resource-path>
<java-charset-name>GBK</java-charset-name>
</input-charset>
</charset-params>
</weblogic-web-app>
测试运行基本正常,总算解决了心中的一个很长时间的困惑。
发表评论
-
求一份fm收音机源码
2011-09-22 14:51 1228本人想做一个FM收音机,但是毫无思路,求高人给一份fm收音机源 ... -
出现一个异常无法解决
2011-04-21 11:19 840com.mysql.jdbc.exceptions.jdbc4 ... -
关于hibernate取值问题,跪求高手帮帮忙
2010-10-19 15:33 1189异常:org.hibernate.exceptio ... -
http上传下载(3)
2010-05-02 23:39 802接类MultipartRequest.java文件尾部 pu ... -
http上传下载(2)
2010-05-02 23:37 841package com.upload.http; import ... -
http上传下载(1)
2010-05-02 23:35 941PubDun package com.upload.htt ... -
关于java的http协议上传
2010-05-02 23:07 755http://blog.sina.com.cn/s/blog_ ... -
ftp上传和下载
2010-05-01 13:05 775Java代码 1.package com.northking ... -
用Java 开发 WebService Axis简单实例
2010-04-29 22:48 785在开发之前, 先了解一下AXIS,axis目前出现的2版本以其 ... -
webservice之axis介绍
2010-04-29 22:45 806webservice之axis介绍1 Axis全称Apache ... -
ftp上传文件
2010-04-29 22:32 775在一般的web应用中,文件上传可以分为两类(ftp上传和htt ...
相关推荐
本文将深入探讨这两种协议的工作原理,并提供它们在Java环境中的实现。 **Xmodem协议** Xmodem是最简单的文件传输协议之一,每一步传输128字节的数据块。它通过校验和机制来检测数据传输中的错误。Xmodem协议分为两...
在Java开发中,文件批量上传是一项常见的功能,尤其在企业级应用中,用户可能需要上传大量数据或文件。本教程将介绍如何利用SWF(Simple Workflow)和EXT库来实现这一功能。SWF是一个用于创建富互联网应用程序的前端...
利用java图形化界面和网络编程相结合实现的--文件上传。 运行步骤: (1)分别运行工程两个包中的两个.java文件(UploadClient.java和UploadServer.java)分别会弹出“上传客服端”和“上传服务器”两个窗口。 ...
在本文中,我们将深入探讨如何使用HttpURLConnection实现文件上传,同时也会涉及普通参数的传递。 首先,我们需要理解HTTP请求的基本结构。HTTP请求通常由以下几个部分组成:请求行、请求头、空行和请求体。在文件...
6. **测试与调试**:在开发过程中,可以使用_cmpp3.0_文件中的样例数据进行单元测试,模拟SMSC的响应,确保协议实现的正确性。此外,日志记录也是必不可少的,它可以帮助开发者在出现问题时快速定位和解决问题。 7....
在实现文件传输时,我们不能一次性发送整个文件,因为UDP的数据报大小受到限制(通常为65535字节)。因此,我们需要将文件拆分成多个小块,每个块作为一个独立的数据报发送。同时,为了确保接收端能正确组装文件,...
总之,Java上传文件到SharePoint是一个涉及网络通信、文件操作和认证授权的复杂过程。理解并掌握这些概念,结合适当的工具或库,可以有效地实现文件在Java应用和SharePoint之间的传输。在阅读给定的博客文章...
java 实现 icmp协议测试 需要在java lib目录下添加libjpcap.so文件
本话题将详细探讨如何通过Ajax实现Java文件的下载,并介绍相关的核心概念和技术。 1. **Ajax**(Asynchronous JavaScript and XML)是一种在不重新加载整个网页的情况下,能够更新部分网页的技术。它通过JavaScript...
本文介绍了 Java 实现文件上传的方法,包括文件上传概述、HTTP 协议简介、Servlet 简介、文件上传实现和文件上传过程等内容。通过本文,读者可以了解 Java 实现文件上传的基本原理和方法,并应用于实际开发中。
3. 模拟POST协议实现文件上传: 有时,我们需要在服务端模拟POST请求来上传文件,例如测试或集成其他API。可以使用`HttpURLConnection`或第三方库如Apache HttpClient来实现。以下是一个使用HttpURLConnection的...
为了在Java中实现文件传输,可以采用UDP协议或者TCP协议。TCP协议提供可靠的数据传输服务,能够保证数据的有序、可靠和无重复地传输,但可能会有较高的延迟。UDP协议不保证数据的传输可靠性,但是它的数据包小,传输...
本篇文章将详细解析如何实现文件上传的Java代码,主要关注`Upload.java`这个类的实现。 首先,理解文件上传的基本原理至关重要。在HTTP协议中,文件上传通常依赖于多部分/形式数据(Multipart/form-data)的请求...
本项目提供了Java版本的SMGP协议实现,且附带了示例代码,方便开发者快速理解和应用。 **1. SMGP协议详解** SMGP协议是一种基于TCP/IP的通信协议,用于连接短信中心(SMSC)和业务系统。协议主要分为三个层次:链路...
1. 文件上传(File Upload) 2. 文件下载(File Download) 3. 文件读取(File Reading) 4、优点: 封装性:工具类封装了NFS相关的复杂连接、认证和I/O操作细节,使得业务层代码无需关心底层通信协议,只需通过...
本文将详细介绍如何使用Java实现大文件的上传并展示进度条,同时解析相关的代码实现。 1. **大文件分块上传** 大文件上传的关键在于避免一次性加载整个文件到内存,因为这可能导致内存溢出。Java中,我们可以使用`...
SCPClient是一个基于ssh的文件传输协议,可以实现文件的上传和下载。通过使用SCPClient,可以实现远程服务器文件的上传和下载。 5. 使用Session实现远程服务器文件的操作 Session是一个远程服务器文件操作的会话,...
在java代码中实现文件的上传和下载,通过页面的file文件上传到java代码段,获取文件的大小和名字
Java实现Xmodem协议主要涉及的是串口通信和数据传输中的错误检测与纠正技术。Xmodem协议是一种早期的文件传输协议,它主要用于通过慢速的串行通信线路进行数据传输,例如调制解调器连接。在Java中实现Xmodem协议,...
Java实现OPC通信协议主要涉及的是Java编程语言与OPC(OLE for Process Control)技术的结合,这是一种在工业自动化领域广泛使用的数据交换标准。在Java中实现OPC通信,通常需要借助于一些开源库或者商业组件,这些库...