通過
Host: 192.168.29.65:80
Content-Type:multipart/form-data;boundary=---------------------------7d33a816d302b6
User-Agent: Mozilla/4.0 (compatible; OpenOffice.org)
Content-Length: 424
Connection: Keep-Alive -----------------------------7d33a816d302b6
Content-Disposition:form-data;
name="userfile1";
filename="E:\s"Content-Type:
application/octet-stream abbXXXccc
-----------------------------7d33a816d302b6
Content-Disposition: form-data;
name="text1" foo
-----------------------------7d33a816d302b6
Content-Disposition: form-data;
name="password1" bar
-----------------------------7d33a816d302b6--
(上面有壹個回車)此內容必須壹字不差,包括最後的回車。
註意:Content-Length: 424 這裏的424是紅色內容的總長度(包括最後的回車)
註意這壹行:Content-Type: multipart/form-data; boundary=---------------------------7d33a816d302b6
根據 rfc1867, multipart/form-data是必須的.---------------------------7d33a816d302b6 是分隔符,分隔多個文件、表單項。
其中33a816d302b6 是即時生成的壹個數字,用以確保整個分隔符不會在文件或表單項的內容中出現。前面的 ---------------------------7d 是 IE 特有的標誌。
Mozila 為---------------------------71用手工發送這個例子,在上述的 servlet 中檢驗通過。
使用POST發送數據
以POST方式發送數據主要是為了向服務器發送較大量的客戶端的數據,它不受URL的長度限制。POST請求將數據以URL編碼的形式放在HTTP正文中,字段形式為fieldname=value,用&分隔每個字段。註意所有的字段都被作為字符串處理。實際上我們要做的就是模擬瀏覽器POST壹個表單。以下是IE發送壹個登陸表單的POST請求:
POST ;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
\r\n
username=admin&password=1234
要在MIDP應用程序中模擬瀏覽器發送這個POST請求,首先設置HttpConnection的請求方式為POST:
hc.setRequestMethod(HttpConnection.POST);
然後構造出HTTP正文:
byte[] data = "username=admin&password=1234".getBytes();
並計算正文長度,填入Content-Type和Content-Length:
hc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
hc.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:
hc.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
--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...