用Java Servlet实现文件上载

太多重名的账号

太多重名的账号

2016-02-19 16:27

下面这个用Java Servlet实现文件上载教程由图老师小编精心推荐选出,过程简单易学超容易上手,喜欢就要赶紧get起来哦!

  各位大侠可能会对263电子邮箱中的"上传附件"功能有印象,就是:在浏览 器中点击"浏览",弹出一个对话框,选中文件后,单击"确定",文件就被上传到了服务器端。 因为需要,就到网上找了几个控件,如SmartUpload等,但都觉得不好用,或者 说是不合用,决定自己做一个。近日看到网上也有人提问怎么上载文件,于是把编制过程整理一遍,希望对大家有所帮助,不足之处,请多多指教。 准备 侦听工具,如SpyNet(包括CaptureNetPeepNet),目的是用于分析数据包格式;

  Java环境:至少要包括一个Servlet引擎,一套JDK;如果没有,可以访问

  "http://www.jsp001.com/article/Application_Server_Comparison_Matrix_20010226.html"

  从这36款中随便找出一种来,安装运行即可。JSP服务器都会支持SERVLET,因为JSP本身就是先被编译成SERVLET再执行的。 过程

  1、制作HTML页面,用于上传文件。需要注意:要指定enctype属性为"multipart/form-data",因为数据流的格式是不一样的。

  form action="/java/servlet/powerise.nms.web.UploadFile"

  method=post enctype="multipart/form-data" p

  input type=radio name=type value=0model

  input type=radio name=type value=1report input name=id

  input type=file name=file value="test" /p

  input type=submit /form

  2、HTML页面做好后,就可以开始分析数据流了。先打开侦听器,然后在浏览器(IE, Netscape)中打开本页面,随意选择一个文件,单击"确定",看看侦听器听到了什么。在跳过前面几个包后,可以得到下面这两个相关的包。

  第一个包的很容易明白,在Servlet中,用getHeader(String)能得到的内容就在这里面。不过这个包,用HttpServletRequest的getInputStream是得不到的。

  关于HTTP协议的更多信息,可以访问www.w3c.org。

  0000: 00 E0 4C DD 2F 4F 00 50 BA A6 C3 CF 08 00 45 00 ..L./O.P......E.

  0010: 02 3E 01 46 40 00 80 06 0E F5 AC 12 C8 01 AC 12 ..F@...........

  0020: C8 58 04 12 00 50 48 82 2A 39 FA 97 28 31 50 18 .X...PH.*9..(1P.

  0030: 44 70 A4 76 00 00 50 4F 53 54 20 2F 6A 61 76 61 Dp.v..POST /java

  0040: 2F 73 65 72 76 6C 65 74 2F 69 6D 63 2E 55 70 6C /servlet/imc.Upl

  0050: 6F 61 64 20 48 54 54 50 2F 31 2E 31 0D 0A 41 63 oad HTTP/1.1..Ac

  0060: 63 65 70 74 3A 20 69 6D 61 67 65 2F 67 69 66 2C cept: image/gif,

  0070: 20 69 6D 61 67 65 2F 78 2D 78 62 69 74 6D 61 70 image/x-xbitmap

  0080: 2C 20 69 6D 61 67 65 2F 6A 70 65 67 2C 20 69 6D , image/jpeg, im

  0090: 61 67 65 2F 70 6A 70 65 67 2C 20 61 70 70 6C 69 age/pjpeg, appli

  00A0: 63 61 74 69 6F 6E 2F 76 6E 64 2E 6D 73 2D 70 6F cation/vnd.ms-po

  00B0: 77 65 72 70 6F 69 6E 74 2C 20 61 70 70 6C 69 63 werpoint, applic

  00C0: 61 74 69 6F 6E 2F 76 6E 64 2E 6D 73 2D 65 78 63 ation/vnd.ms-exc

  00D0: 65 6C 2C 20 61 70 70 6C 69 63 61 74 69 6F 6E 2F el, application/

  00E0: 6D 73 77 6F 72 64 2C 20 2A 2F 2A 0D 0A 52 65 66 msword, */*..Ref

  00F0: 65 72 65 72 3A 20 68 74 74 70 3A 2F 2F 31 37 32 erer: http://172

  0100: 2E 31 38 2E 32 30 30 2E 38 38 2F 64 65 6D 6F 2F .18.200.88/demo/

  0110: 74 65 73 74 2E 68 74 6D 6C 0D 0A 41 63 63 65 70 test.html..Accep

  0120: 74 2D 4C 61 6E 67 75 61 67 65 3A 20 7A 68 2D 63 t-Language: zh-c

  0130: 6E 0D 0A 43 6F 6E 74 65 6E 74 2D 54 79 70 65 3A n..Content-Type:

  0140: 20 6D 75 6C 74 69 70 61 72 74 2F 66 6F 72 6D 2D multipart/form-

  0150: 64 61 74 61 3B 20 62 6F 75 6E 64 61 72 79 3D 2D data; boundary=-

  0160: 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D ----------------

  0170: 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 37 64 31 33 35 32 ----------7d1352

  0180: 61 32 30 31 36 63 0D 0A 41 63 63 65 70 74 2D 45 a2016c..Accept-E

  0190: 6E 63 6F 64 69 6E 67 3A 20 67 7A 69 70 2C 20 64 ncoding: gzip, d

  01A0: 65 66 6C 61 74 65 0D 0A 55 73 65 72 2D 41 67 65 eflate..User-Age

  01B0: 6E 74 3A 20 4D 6F 7A 69 6C 6C 61 2F 34 2E 30 20 nt: Mozilla/4.0

  01C0: 28 63 6F 6D 70 61 74 69 62 6C 65 3B 20 4D 53 49 (compatible; MSI

  01D0: 45 20 35 2E 30 31 3B 20 57 69 6E 64 6F 77 73 20 E 5.01; Windows

  01E0: 4E 54 20 35 2E 30 29 0D 0A 48 6F 73 74 3A 20 31 NT 5.0)..Host: 1

  01F0: 37 32 2E 31 38 2E 32 30 30 2E 38 38 0D 0A 43 6F 72.18.200.88..Co

  0200: 6E 74 65 6E 74 2D 4C 65 6E 67 74 68 3A 20 34 30 ntent-Length: 40

  0210: 39 0D 0A 43 6F 6E 6E 65 63 74 69 6F 6E 3A 20 4B 9..Connection: K

  0220: 65 65 70 2D 41 6C 69 76 65 0D 0A 43 6F 6F 6B 69 eep-Alive..Cooki

  0230: 65 3A 20 4A 53 45 53 53 49 4F 4E 49 44 3D 63 74 e: JSESSIONID=ct

  0240: 71 62 76 65 38 73 35 31 0D 0A 0D 0A qbve8s51....

  再看第二个包,可以看到,所要传的参数都在。下文只分析这个包。

  0000: 00 E0 4C DD 2F 4F 00 50 BA A6 C3 CF 08 00 45 00 ..L./O.P......E.

  0010: 01 C1 01 47 40 00 80 06 0F 71 AC 12 C8 01 AC 12 ...G@....q......

  0020: C8 58 04 12 00 50 48 82 2C 4F FA 97 28 31 50 18 .X...PH.,O..(1P.

  0030: 44 70 3D AE 00 00 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D Dp=...----------

  ↑(1)开始

  0040: 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D ----------------

  0050: 2D 2D 2D 37 64 31 33 35 32 61 32 30 31 36 63 0D ---7d1352a2016c.

  0060: 0A 43 6F 6E 74 65 6E 74 2D 44 69 73 70 6F 73 69 .Content-Disposi

  0070: 74 69 6F 6E 3A 20 66 6F 72 6D 2D 64 61 74 61 3B tion: form-data;

  0080: 20 6E 61 6D 65 3D 22 74 79 70 65 22 0D 0A 0D 0A name="type"....

  0090: 30 0D 0A 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 0..-------------

  ↑(2)第1段结束

  00A0: 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D ----------------

  00B0: 37 64 31 33 35 32 61 32 30 31 36 63 0D 0A 43 6F 7d1352a2016c..Co

  00C0: 6E 74 65 6E 74 2D 44 69 73 70 6F 73 69 74 69 6F ntent-Dispositio

  00D0: 6E 3A 20 66 6F 72 6D 2D 64 61 74 61 3B 20 6E 61 n: form-data; na

  00E0: 6D 65 3D 22 69 64 22 0D 0A 0D 0A 36 37 38 0D 0A me="id"....678..

  00F0: 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D ----------------

  ↑(3)第2段结束

  0100: 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 37 64 31 -------------7d1

  0110: 33 35 32 61 32 30 31 36 63 0D 0A 43 6F 6E 74 65 352a2016c..Conte

  0120: 6E 74 2D 44 69 73 70 6F 73 69 74 69 6F 6E 3A 20 nt-Disposition:

  0130: 66 6F 72 6D 2D 64 61 74 61 3B 20 6E 61 6D 65 3D form-data; name=

  0140: 22 66 69 6C 65 22 3B 20 66 69 6C 65 6E 61 6D 65 "file"; filename

  0150: 3D 22 43 3A 5C 43 4F 4E 46 49 47 2E 53 59 53 22 ="C:CONFIG.SYS"

  0160: 0D 0A 43 6F 6E 74 65 6E 74 2D 54 79 70 65 3A 20 ..Content-Type:

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

  0170: 74 65 78 74 2F 70 6C 61 69 6E 0D 0A 0D 0A 73 68 text/plain....sh

  0180: 65 6C 6C 3D 63 3A 5C 63 6F 6D 6D 61 6E 64 2E 63 ell=c:command.c

  0190: 6F 6D 20 2F 70 20 2F 65 3A 33 32 30 30 30 0D 0A om /p /e:32000..

  01A0: 0D 0A 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D ..--------------

  ↑(4)第3段结束

  01B0: 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 37 ---------------7

  01C0: 64 31 33 35 32 61 32 30 31 36 63 2D 2D 0D 0A d1352a2016c--..

  (5)结束 ↑

  以下对各标号作出说明: (1)开始,这是整个能得到的输入流的开端;

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)

  (2)第1段结束。每一段包含一个参数的信息,这些信息包括类型、名称、内容等。 (3)和(4)与(2)是一样的。

  (4)以后就是输入流的结束标志:boundary。 (5)为从输入流中能读到的最后一个字符。

  注意了第一个包中,有一项叫做"boundary"。顾名思义,这个boundary是"分界"标志了。每一段的开头都会有一个boundary,然后是 0D 0A,然后是一些相关信息,接着是 0D 0A 0D 0A,紧跟着参数的实际值,然后是下一个boundary,标志着下一段的开始。而整个输入流呢,以一个boundary结束。如果只有一个参数,那输入流的结构应该是下面这样的:

  boundary 0D 0A ... 0D 0A 0D 0A ... boundary 0D 0A

  ↑ ↑ ↑ ↑

  开始 参数的信息 参数的内容 结束明白了数据流的结构,编程就简单了,以下给出一段源程序。该程序易于使用,(当然,也不必交版权费)。先给出如下的调用示例,而把源程序附于末尾。

  public void doPost(HttpServletRequest req, HttpServletResponse resp)

  throws ServletException, java.io.IOException {

  //新建一个对象,其实,若写成static的,连这一步都可省了

  DecodeRequestStream decode = new DecodeRequestStream();

  //调用Decode方法,返回一个哈希表 Hashtable hashtable = decode.Decode(req, 2); ......

  //获取type的值 String type = (String)hashtable.get("type"); //获取id的值String id = (String)hashtable.get("id"); //以字节数据的方式获得文件的内容byte[] filecontent = (byte[])hashtable.get("file"); ...... }

  Decode函数的声明如下: 入参: (1)HttpServletRequest: 从这个参数中可以得到输入流;

  (2)int ParamsCount: 这个参数表示输入流中除文件外,普通参数的个数提供这个参数是从性能的角度出发的,下文中会有说明; 出参:

  一个哈希表。如果是普通参数,则以(string name, string value)的方式保存,如果是文件,则以(string name, byte[] value)的方式保存;

  对DecodeRequestStream类,作如下说明: 1、本类一次只能处理一个文件的上载。如果有多个文件,将会保存在一个字节数组里面。实际上,可以很容易地把本程序改写成支持多文件的。我这 么做也是从性能方面考虑;个人认为,已经够用了;

  2、文件必须是作为最后一个参数。此前有多少个参数必须在调用时通过ParamsCount参数指定。细心的大侠会发现这个参数也是为了性能。因为确定边界boundary的位置是一个很费时的操作,需要先拷贝某个位置起与boundary相同长度的字节数组,然后再与boundary比较。在确定文件内容的结束位置时,要从文件流的开始处一直搜索到文件的结束处,对于大的文件,这是很费时的。所以本程序中做了一点小动作,那就是,对于第ParamsCount+1 的那个参数(也就是文件参数),不用常规方法搜索,而是直接跳到输入流的末尾(末尾是boundary 0D 0A),再往前倒数boundary的长度外加4个字节。

  然后从这个位置开始定位boundary(一找一个准)。程序中,用了5个字节, 是"留有余地"的想法,其实不用。

  3、本程序在 Tomcat 3.2.1 + Sun JDK 1.3.0_02 下运行通过,客户端浏览器为Internet Exploere 5.0、Netscape Communacator 4.77 和Netscape 6。以下是源程序:

  

DecodeRequestStream.java
---------------------------------------------------------------------------
import javax.servlet.*;import javax.servlet.http.*;import java.io.*;
import java.util.*;public class DecodeRequestStream{
public Hashtable Decode(HttpServletRequest req, int paramcount)
throws java.io.IOException { byte[] body = null; int bodyLen = 0;
byte[] bound = null; int boundLen = 0; int index = 0; int count = 0;
bodyLen = req.getContentLength(); body = new byte[bodyLen];
BufferedInputStream dataIn= new BufferedInputStream( req.getInputStream());
int readed = 0; int cur_read = 0; while (readed bodyLen)
{ cur_read = dataIn.read(body, readed, bodyLen-readed);
if (cur_read 0) { break; }
readed = readed + cur_read; } int i = 0;
while (i = bodyLen) {
if (body[i] == 13 && body[i+1] == 10) break; else
i ++; } if (i bodyLen) return null;
boundLen = i; bound = new byte[boundLen];
for (int j=0; jboundLen; j++) {
bound[j] = body[j + index]; //decode bound }
i = i+2; //plus 2 to skip the following bytes "0D 0A"
index = i; //point to the beginning of first parameter
Hashtable hashtable = new Hashtable(); boolean moved = false;
while (i bodyLen) { if (!moved && count == paramcount)
{
i = bodyLen-boundLen-5; //subst more than 4, but little than 10
moved = true; }
if (!compareByteArray(copybyte(body, i, boundLen), bound)) {
i++; } else { count ++;
int j = index;
while ((j i) && (body[j] != 13 || body[j+1] != 10 ||
body[j+2]!=13 || body[j+3] != 10)) { j ++;
} if (j = i) break;
String paramHeader = new String(body, index, j-index+2);
index = j; int m = paramHeader.indexOf("name="");
if (m 0) break; m = m+6; //point to name value
int n = paramHeader.indexOf(""", m); if (n = m) break;
String name = paramHeader.substring(m, n); //get name
boolean isFile = false; String filename = "";
String filetype = "";
m = paramHeader.indexOf("filename="", n+1); if (m n)
{ isFile = true; m = m+10; //skip (filename=")
n = paramHeader.indexOf(""", m);
if (n m) filename = paramHeader.substring(m, n);
m = paramHeader.indexOf("Content-Type: ", n+1); if (m n)
{ m = m+14; n = m;
while ((n paramHeader.length())
&& (paramHeader.charAt(n) != 13
|| paramHeader.charAt(n+1) != 10)) { n++;
} if (n = paramHeader.length())
filetype=paramHeader.substring(m, n); } }/*
status: j point to the start of end flag (0D 0A 0D 0A) of current parameter´s
header after j + 0D 0A 0D 0A, is the start of current parameter´s value
(byte format) i point to the start of next boundary, that is,
"(current header) 0D 0A 0D 0A (current value) 0D 0A (next boundary)"
↑ ↑ ↑
index j i
the following code gets current value*/
j = j+4; //skip 0D 0A 0D 0A, point to parameter value;
byte[] value = copybyte(body, j, i-j-2); if (!isFile)
{ String tmpstr = new String(value);
hashtable.put(name, tmpstr); } else {
hashtable.put(name, value); break; }
i = i + boundLen + 2; index = i; } //end else
} //end while dataIn.close(); return hashtable; }
public boolean compareByteArray(byte[] a, byte[] b) {
if (a.length != b.length) return false; for (int i=0; ia.length; i++)
if (a[i] != b[i]) return false; return true; }
public byte[] copybyte(byte[] a, int from, int len) { int copylen = len;
if ((a.length-from) copylen) copylen = a.length-from;
byte[] b = new byte[copylen]; for (int i=0; icopylen; i++) b[i] = a[from+i];
return b; }}----------------------------------------------------------

展开更多 50%)
分享

猜你喜欢

用Java Servlet实现文件上载

编程语言 网络编程
用Java Servlet实现文件上载

用JSP文件上载轻松实现

Java JAVA基础
用JSP文件上载轻松实现

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

用PHP3实现文件上载

PHP
用PHP3实现文件上载

用JavaBean实现文件上载(一)请求分析

编程语言 网络编程
用JavaBean实现文件上载(一)请求分析

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

用java实现外部调用exe文件

编程语言 网络编程
用java实现外部调用exe文件

用Java实现HTTP文件队列下载

Java JAVA基础
用Java实现HTTP文件队列下载

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

构建基于Web/XML的信息集成研究

构建基于Web/XML的信息集成研究

Java、Java Applet与 JavaScript间的通信

Java、Java Applet与 JavaScript间的通信
下拉加载更多内容 ↓