JSP/SERVLET上載的難點 支持任意格式
任意數量的文件上載
上載控制的實現
表單信息的取得
即插即用
的應用方法
我個人認為
制約通用 上載組件的實現主要是這四個難點
JSP/SERVLET上傳的原理 JSP/SERVLET文件 上載是通過ServletInputStream類來實現的
ServletInputStream類是java
io
InputStream的一個擴展抽象類
實質上也是一個輸入流
通過ReadLine方法從Request端一行一行讀取
可見
JSP/SERVLET上載根本上是用流來實現的
理解了這個就不難理解整個 上載的原理
ServletInputStream實現文件 上載必須采用HTTP POST或者HTTP PUT協議
HTTP GET協議只能傳遞很少的數據
是不能實現文件上載的
下面我們來看一下上傳的數據流的結構
首先要在BROWSER端給出一個請求
我們的請求如下(文件名為test
jsp):
<%@ page contentType=
text/html; charset=GBK
%>
<html>
<head>
<title>文件上載</title>
</head>
<body>
<form action=
test
jsp
enctype=
MULTIPART/FORM
DATA
method=post>
說明一: <input type=
text
name=
explain
/>
<br />
說明二: <input type=
text
name=
explain
/>
<br />
請選擇上載文件
<input type=
file
name=
file
/>
<br />
請選擇上載文件
<input type=
file
name=
file
/>
<br />
說明三: <input type=
text
name=
explain
/>
<br />
<input type=
submit
value=
上 載
/>
</form>
</body>
</html>
顯示如下
說明一
說明二
請選擇上載文件一
請選擇上載文件二
說明三
在上載請求頁中混雜了表單的三個輸入框
及兩個上載文件
當然輸入框可以更多
更雜
可以有選擇框
單選及多選按鈕
待上傳的文件也可以有三個
四個或所需要的更多
action=
test
jsp
表示表單將提交到
test
jsp
另外注意表單屬性中必須要有這句
enctype=
MULTIPART/FORM
DATA
enctype指定 Form 輸入資料的編碼方式
method
屬性必須為
post
這樣表單才能提交大量數據
也表示本表單的數據傳遞將用流操作
method=get
表示數據將通過地址欄進行傳遞
雖然方便快捷
但只適合很少的數據量
響應端
test
jsp
頁面如下
<%@ page contentType=
text/html; charset=GBK
%>
<html>
<head>
<title>文件上載</title>
</head>
<body>
<jsp:useBean id=
upBean
scope=
page
class=
com
upload
UpBean
/>
<%
upBean
doUpload(request);
out
println(
上載已完成
請查看輸出文件
);
%>
</body>
</html>
test
jsp收到請求後
調用一個java bean執行doUpload(request)操作
本操作將完成流(unicode格式)的接收並不做任何處理地將流順序寫入一個文本文件裡
讀寫操作中用了一個緩沖區byte[] readByte
用了一個ServletInputStream 的一個方法readLine(byte[] b
int off
int len)方法讀取流
請大家注意
ServletInputStream 流的read Line方法是一次讀入指定大小的行
java bean (UpBean
java)代碼如下
[code]package com
upload;
import java
io
*;
import javax
servlet
*;
import javax
servlet
http
HttpServletRequest;
import javax
servlet
ServletInputStream;
public class UpBean {
public void doUpload(HttpServletRequest req) throws ServletException
IOExcept
ion{
//首先定義一個文本文件
File file = new File(
out
txt
);
//readCount 記錄從輸入流中實際讀取的字符數
int readCount;
//輸入流緩沖區
byte[] readByte = new byte[
];
//初始化輸入流
ServletInputStream servletInputStream = req
getInputStream();
//初始化一個輸出流(到文件)
FileOutputStream fileOutputStream = new FileOutputStream(file);
//循環從讀取輸入流中讀取字節
readCount = servletInputStream
readLine(readByte
readByte
length);
while(readCount !=
){
fileOutputStream
write(readByte
readCount);
readCount = servletInputStream
readLine(readByte
);
}
//關閉文件流
fileOutputStream
flush();
}
}[/code]
為了便於我們閱讀流
上載的兩個文件為兩個簡單的文本文件(有格式的文件
不便於直接分析)
one
txt及two
txt
文件內容如下
實驗時請建立對應文本文件
內容請直接copy以下所示
one
txt:
one
one one
one one one
two
txt
two
two two
two two two
都准備好以後
我們就可以運行了
運行時請注意
文本部分及文件部分最好不要出現漢字
或其他雙字符集字符
盡量采用英文
因為接收是采用的Unicode字符集
我們未對輸入做任何處理
我們在三個輸入框輸入的字符為
說明一
explain
說明二
explain
說明三
explain
out
txt接收到如下字符
d
a
e
Content
Disposition: form
data; name=
explain
explain
d
a
e
Content
Disposition: form
data; name=
explain
explain
d
a
e
Content
Disposition: form
data; name=
file
; filename=
C:\test\one
txt
Content
Type: text/plain
one
one one
one one one
d
a
e
Content
Disposition: form
data; name=
file
; filename=
C:\test\two
txt
Content
Type: text/plain
two
two two
two two two
d
a
e
Content
Disposition: form
data; name=
explain
explain
d
a
e
可以很明顯的看到
out
txt被
d
a
e
分成了五 節
即表單的每個輸入部分都對應一節
結尾部分是
d
a
e
剛好比開始的一段字符在最後多出兩個
每節的第一行是輸入內容的說明
Content
Disposition: form
data
name=
explain
表示 上載請求項的name
文本輸入部分僅這兩個說明
如果輸入的是文件還用兩項說明
filename=
C:\test\one
txt
表示輸入源
基於ms
windows的ie上載帶有完整的路徑
netscape及其他浏覽器可能只有一個文件名
還有一項是關於輸入格式的
Content
Type:text/plain
表示輸入格式是文本類型
如果我們上載的是bmp文件則為
Content
Type: image/bmp
word文件為
application/msword
說明的下面緊接著是一個空行
然後下面才是我們所需的內容
仔細分析未加修改的輸入流格式
有助於我們實現文件與輸入文本的准確分離
通過以上的分析可以看出
准確分離上載的文件及文本信息需要以下要素
數據段分割符
結束符(比分割符多出兩個
)
輸入文本及上載的文件區分標志(文本為
name=
文件為
filename=
)
編碼格式
可以通過HttpServletRequest 類getCharacterEncoding() 方法取得
表單文本部分名稱及內容
名稱為
name=
後面的字符
內容為該段第三行及以後的內容
文件名稱及內容
名稱為
filename=
後面的字符
內容為該段第三行及以後的內容
下面我們將討論輸入流的分離
程序實現分析 我們首先畫出程序實現的主體結構圖
請注意判斷文件標志(indexOf(
filename=
)>
)
與判斷文本標志(indexOf(
name=
)>
)的順序
當(indexOf(
filename=
)>
)成立時
(indexOf(
name=
)>
)一定也是成立的
所以判斷文件要在判斷文本前
分離文件及輸入文本
為完整保存上載的文件信息及輸入的文本信息
本程序建立了兩個類
public class FileInfo
public class InputField
及兩個線性表private ArrayList upFilesList
private ArrayList inputFieldList
用於動態增加文件信息及文本信息
定義如下
FileInfo
java(記錄上載文件信息)
package com
upload;
public class FileInfo {
private String fileName;
private boolean validFlag;
private String filePath;
private long fileSize;
//設置文件信息
//上載文件是否有效標志
public void setValidFlag(boolean validFlag){
this
validFlag = validFlag;
}
//文件名
public void setFileName(String filename){
this
fileName = filename;
}
//存貯路徑
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19662.html