請求分析 要實現文件上載,我們必須先了解上載文件的HTTP請求。下面這個簡單的應用示范了如何上載文件以及把HTTP請求的原始數據寫入文件。用文本編輯器查看該文件即可了解請求的格式,在此基礎上我們就可以提取出上載文件的名字、文件內容以及原本混合在一起的其他信息。
<!-- frame contents -->
<!-- /frame contents -->
這個簡單的應用是開發真正文件上載JavaBean的預備工作。它由三個文件構成:Html文件main.html,jsp頁面Jsp1.jsp,JavaBean文件SimpleBean.java。
main.html提供一個表單,用戶從這裡選擇文件並把文件上載到服務器。main.html的代碼如下:
<html>
<head>
<title>文件上載</title>
</head>
<body>
<form action="jsp1.jsp" enctype="MULTIPART/FORM-DATA" method=post>
作者: <input type="text" name="author" />
<br />
公司: <input type="text" name="company" />
<br />
選擇要上載的文件 <input type="file" name="filename" />
<br />
<input type="submit" value="上載" />
</form>
</body>
</html> 可以看到,<form>標記有一個enctype屬性,屬性值是"MULTIPART/FORM-DATA"。包括提交按鈕在內,表單裡面共有4個輸入元素。前面兩個輸入元素是普通的text元素,即author和company。第三個輸入元素的type屬性是file,這個輸入元素就是用來選擇文件的元素。
進入討論組討論。
表單的action屬性值是Jsp1.jsp,這意味著請求(包括上載的文件)將發送給Jsp1.jsp文件。Jsp1.jsp簡單地調用名為SimpleBean的JavaBean。
<jsp:useBean id="TheBean" scope="page" class="SimpleBean " />
<%
TheBean.doUpload(request);
%>
<!-- frame contents -->
<!-- /frame contents -->
下面是SimpleBean的實現代碼: import java.io.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletInputStream;
public class FileUploadBean {
public void doUpload(HttpServletRequest request) throws
IOException {
PrintWriter pw = new PrintWriter(
new BufferedWriter(new FileWriter("Demo.out")));
ServletInputStream in = request.getInputStream();
int i = in.read();
while (i != -1) {
pw.print((char) i);
i = in.read();
}
pw.close();
}
}
進入討論組討論。
這個JavaBean把HttpServletRequest對象的表單原始數據寫入Demo.out文件。應用的用戶界面由main.html文件提供,如下圖所示。
我們選擇上載的文件是abisco.html。選擇上載HTML文件是為了便於觀察上載後的格式,因為HTML文件本質上是文本文件,我們可以方便地浏覽其內容。abisco.html文件的內容如下:
<html>
<head>
<title>Abisco</title>
</head>
</html>
點擊“上載”按鈕之後,表單就發送給了Jsp1.jsp文件,一起發送的還有abisco.html文件。Jsp1.jsp文件不會向浏覽器發送任何應答內容,但它會生成一個Demo.out文件。
進入討論組討論。
打開Demo.out文件,我們可以看到如下內容:
-----------------------------7d15340138
Content-Disposition: form-data; name="Author"
A. Christie
-----------------------------7d15340138
<!-- frame contents -->
<!-- /frame contents -->
Content-Disposition: form-data; name="Company"
Abisco
-----------------------------7d15340138
Content-Disposition: form-data; name="Filename"; filename="C:123dataabisco.html"
Content-Type: text/html
<html>
<head>
<title>Abisco</title>
</head>
</html>
-----------------------------7d15340138--
可以看到,HTTP請求體內包含了所有的表單輸入,包括上載的文件。這些輸入數據的分隔由一個分隔符實現。分隔符由一系列的“-”字符和一個隨機數字構成。在上面的例子中,分隔符為“-----------------------------7d15340138”。最後一個分隔符結束請求體,這個分隔符的後面多出兩個“-”符號。
進入討論組討論。
對於非文件類型的輸入數據,分隔符後面跟著下面這行內容:Content-Disposition: form-data; name=inputName。其中inputName是表單元素的名字。例如:Content-Disposition: form-data; name="Author"。在這行內容的後面,緊跟著兩個連續的回車換行符和表單元素值。
<!-- frame contents -->
<!-- /frame contents -->
而對於文件型輸入域,分隔符的後面有兩行內容。第一行內容包含輸入元素的名字以及上載文件在客戶端的完整路徑,如上例中這行內容是“Content-Disposition: form-data; name="Filename"; filename="C:123dataabisco.html"”。這行內容指出文件輸入元素的名字是filename,文件的路徑是“C:123dataabisco.html”。注重Windows浏覽器會設置文件路徑,而Unix/Linux以及Mac浏覽器只發送文件名字。
第二行包含了文件的內容類型,因此它的具體內容和上載的文件有關。本例中第二行的內容是“Content-Type: text/html”。
和非文件輸入元素一樣,文件內容在兩個連續的回車換行符之後正式開始。
進入討論組討論。