由于項目的需要,使用Applet實作檔案上傳被提上日程,作者關于applet實作檔案上傳google了N次,baidu了m次,終于搞定。最大的感觸就是網上的資料有時候會誤導你,需要不停的做實驗,不停地尋找出現問題的解決方案。作者由于幾個比較關鍵的地方網上的資料未提供,在此作為記錄,希望能對新手提供一些有用的參考。
關于檔案上傳的原理,可以baidu一下,網上的資料說得比較明白,在這裡略微提一下,檔案通過html上傳需要設定送出form表單的表單元素的enctype=” multipart/form-data” 原理是,通過為表單元素設定enctype=”multipart/form-data”屬性,讓表單送出的資料以二進制編碼的方式送出,在接收此請求的Servlet中用二進制流來擷取内容,就可以取得上傳檔案的内容,進而實作檔案的上傳。檔案上傳後在伺服器端得表示如下(選擇文本):
當上面檔案執行以後會産生如下結果:(選擇的上傳檔案不同,結果類似)
(1) -----------------------------7d45a76025c
(2) Content-Disposition: form-data; name="text1"; filename=" D:\1.txt"
(3) Content-Type: text/plain
(4)
(5) public static void main(String[] args) {
(6) FileUtil.makeDir("dir1/dir2/dir3/dir4","c:/java/");
(7) }
(8) }
(9)
(10) -----------------------------7d45a76025c--
其中第一行為分界符,和(10)行一樣,第(10)行作為分界符的結尾,注意,比第一行在最後多出兩個“-“。第4,9行為空行,5-8行為需要寫入二進制檔案或者文本的地方。網上的一些資料沒有講這一部分,需要特别留意。
了解了檔案上傳的格式,就可以使用applet向伺服器端寫入以上格式的内容,就可以實作把檔案上傳到伺服器端了。如果伺服器端使用Struts2,則架構為我們接收了檔案,就不用寫servlet了。Struts2可以處理以POST方式送出的資料。下面講述開發的用戶端代碼,伺服器端的代碼如果不清楚,可以參看Struts2的官方文檔。
假設系統使用UTF-8編碼,用戶端調用Applet上傳檔案的代碼
String url=http://127.0.0.1:8080/upload.action//接收檔案的action
HttpURLConnection con = (HttpURLConnection) new URL(url) .openConnection();//打開連接配接
String boundary=”-------------------------123456”;//設定的分解符比實際用的少2個“-“
String twoHypeLine=” -- “;
String lineEnd=”\r\n”;
con.setDoOutput(true);
conn.setUseCaches(false);
// Use a post method.POST為大寫
conn.setRequestMethod("POST");
con.setRequestProperty("Accept", "*/*");
con.setRequestProperty("Accept-Language", "zh-cn");
//設定分隔符
con.setRequestProperty("Content-Type",
"multipart/form-data; boundary="+boundary);
con.setRequestProperty("Accept-Encoding", "gzip, deflate");
con.setRequestProperty("Connection", "Keep-Alive");
con.setRequestProperty("Cache-Control", "no-cache");
// 設定流式輸出的請求頭和請求尾
String header =( twoHypeLine + twoHypeLine +boundary+lineEnd+
+ "Content-Disposition: form-data; name=\"upload\"; filename=\"%s\" " +lineEnd+ "Content-Type: application/octet-stream "+ lineEnd+ lineEnd;
//name屬性可以了解為<input type=”file”>中的name屬性,在Struts2中被解析為uploadFileName屬性
//content-type在Struts2中被解析為UploadContentType
byte[] tailbyte =( lineEnd + twoHypeLine +boundary+ twoHypeLine+ lineEnd) .getBytes();
//檔案名種包含中文時,一定要記得使用utf-8
byte[] headByte = String.format(header, file.getName()).getBytes(“utf-8”);
// 設定請求體的長度(直接輸出,避免在本地進行緩存),同時連接配接伺服器
con.setFixedLengthStreamingMode((int) file.length() + headByte.length+ tailbyte.length);
con.connect();
// 寫檔案流到請求體中
OutputStream dos = con.getOutputStream();
dos.write(headByte); // 寫檔案頭
//file為本地打開的檔案
FileInputStream fis = new FileInputStream(file);
int len = 0;
byte b[] = new byte[blockSize];
while (len != -1) {
len = fis.read(b);
if (len > 0) {
dos.write(b, 0, len);
dos.flush();
uploadStatus.upload(len);
}
}
fis.close();
dos.write(tail);
dos.close();
至此檔案基本上可以正确的寫入到伺服器端,那麼如何從伺服器端讀取哪?上傳之後的檔案可以通過json格式回傳資料,在Struts2中隻需要設定為傳回類型為json即可,
InputStream is = con.getInputStream();
byte[] response = new byte[is.available()];
is.read(response);
JsonObject jo=new JsonObject(new String(response.getBytes(“UTF-8”)));
由于回傳的資料為UTF-8格式的,必須通過轉碼才能被JSON對象識别,對于傳回的資料,可以做你想做的任何處理,比如在頁面上顯示等等。當然在上傳過程中可以實作進度條。
祝
君好運。
參考網站: http://mupload.googlecode.com
http://blog.csdn.net/Breeze2003/archive/2008/09/22/2962177.aspx