含義 ENCTYPE="multipart/form-data" 說明:
通過 http 協議上傳文件 rfc1867協議概述,客戶端發送內容構造。
概述
在最初的 http 協議中,沒有上傳文件方面的功能。 rfc1867為 http 協議添加了這個功能。客戶端的瀏覽器,如 Microsoft IE, Mozila, Opera 等,按照此規范將用戶指定的文件發送到服務器。服務器端的網頁程序,如 php, asp, jsp 等,可以按照此規范,解析出用戶發送來的文件。Microsoft IE, Mozila, Opera 已經支持此協議,在網頁中使用一個特殊的 form 就可以發送文件。絕大部分 http server ,包括 tomcat ,已經支持此協議,可接受發送來的文件。各種網頁程序,如 php, asp, jsp 中,對於上傳文件已經做了很好的封裝。
實例
<form action="upFile.php" enctype="multipart/form-data" method="post"> <input name="myflie" type="file" /> <input type="submit" />
注意 enctype="multipart/form-data", method=post, type="file" 。根據 rfc1867, 這三個屬性是必須的。multipart/form-data 是新增的編碼類型,以提高二進制文件的傳輸效率。
數據傳輸

格式 必須一字不差,包括最后的回車。
注意:Content-Length: 226 這里的226是紅色內容的總長度(包括最后的回車)
注意這一行:
Content-Type: multipart/form-data; boundary=-----------------------------264141203718551
根據 rfc1867, multipart/form-data是必須的.---------------------------7d33a816d302b6 是分隔符,分隔多個文件、表單項。
其中7d33a816d302b6 是即時生成的字符串,用以確保整個分隔符不會在文件或表單項的內容中出現。
使用POST發送數據
以POST方式發送數據主要是為了向服務器發送較大量的客戶端的數據,它不受URL的長度限制。POST請求將數據以URL編碼的形式放在HTTP正文中,字段形式為fieldname=value,用&分隔每個字段。注意所有的字段都被作為字符串處理。實際上我們要做的就是模擬瀏覽器POST 一個表單。以下是IE發送一個登陸表單的POST請求:
POST http://127.0.0.1/login.do HTTP/1.0 Accept: image/gif, image/jpeg, image/pjpeg, */* Accept-Language: en-us,zh-cn;q=0.5 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) Content-Length: 28
username=admin&password=1234
要在MIDP應用程序中模擬瀏覽器發送這個POST請求,首先設置HttpConnection的請求方式為POST(PHP為curl):
// 使用POST方法
httpURLConnection.setRequestMethod("POST");
然后構造出HTTP正文:
byte[] data = "username=admin&password=1234".getBytes();
並計算正文長度,填入Content-Type和Content-Length:
httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
httpURLConnection.setRequestProperty("Content-Length", String.valueOf(data.length));
然后打開OutputStream將正文寫入:
OutputStream output = hc.openOutputStream(); output.write(data);
需要注意的是,數據仍需要以URL編碼格式編碼,由於MIDP庫中沒有J2SE中與之對應的URLEncoder類,因此,需要自己動手編寫這個 encode()方法,可以參考java.net.URLEncoder.java的源碼。剩下的便是讀取服務器響應,代碼與GET一致,這里就不再詳述。
使用multipart/form-data發送文件
如果要在MIDP客戶端向服務器上傳文件,我們就必須模擬一個POST multipart/form-data類型的請求,Content-Type必須是multipart/form-data。
以multipart/form-data編碼的POST請求格式與application/x-www-form-urlencoded完全不同,multipart/form-data需要首先在HTTP請求頭設置一個分隔符,例如ABCD:
httpURLConnection.setRequestProperty("Content-Type", "multipart/form-data; boundary=ABCD");
然后,將每個字段用“--分隔符”分隔,最后一個“--分隔符--”表示結束。例如,要上傳一個title字段"Today"和一個文件C:\1.txt,HTTP正文如下:
--ABCD Content-Disposition: form-data; name="title" \r\n Today --ABCD Content-Disposition: form-data; name="1.txt"; filename="C:\1.txt" Content-Type: text/plain \r\n <這里是1.txt文件的內容> --ABCD-- \r\n
請注意,每一行都必須以\r\n結束,包括最后一行。如果用Sniffer程序檢測IE發送的POST請求,可以發現IE的分隔符類似於 ---------------------------7d4a6d158c9,這是IE產生的一個隨機數,目的是防止上傳文件中出現分隔符導致服務器無法正確識別文件起始位置。我們可以寫一個固定的分隔符,只要足夠復雜即可。
發送文件的POST代碼如下:
String[] props = ... // 字段名
String[] values = ... // 字段值
byte[] file = ... // 文件內容
String BOUNDARY = "---------------------------7d4a6d158c9"; // 分隔符
StringBuffer sb = new StringBuffer();
// 發送每個字段:
for(int i=0; i
sb = sb.append("--");
sb = sb.append(BOUNDARY);
sb = sb.append("\r\n");
sb = sb.append("Content-Disposition: form-data; name=\""+ props[i] + "\"\r\n\r\n");
sb = sb.append(URLEncoder.encode(values[i]));
sb = sb.append("\r\n");
}
// 發送文件:
sb = sb.append("--");
sb = sb.append(BOUNDARY);
sb = sb.append("\r\n");
sb = sb.append("Content-Disposition: form-data; name=\"1\"; filename=\"1.txt\"\r\n");
sb = sb.append("Content-Type: application/octet-stream\r\n\r\n");
byte[] data = sb.toString().getBytes();
byte[] end_data = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();
// 設置HTTP頭:
hc.setRequestProperty("Content-Type", MULTIPART_FORM_DATA + "; boundary=" + BOUNDARY);
hc.setRequestProperty("Content-Length", String.valueOf(data.length + file.length + end_data.length));
// 輸出:
output = hc.openOutputStream();
output.write(data);
output.write(file);
output.write(end_data);
// 讀取服務器響應:
// TODO...

