在 J2ME 中發送 HTTP POST 請求,關鍵在於正確設定請求標頭與資料寫入順序。以下是最精簡且完整的範本:
HttpConnection conn = null;
OutputStream out = null;
try {
// 1. 建立連線
conn = (HttpConnection) Connector.open(url);
// 2. 設定請求方法與標頭 (順序很重要)
conn.setRequestMethod(HttpConnection.POST);
conn.setRequestProperty("User-Agent", "Profile/MIDP-1.0 Configuration/CLDC-1.0");
conn.setRequestProperty("Content-Language", "en-US");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Accept", "application/octet-stream");
conn.setRequestProperty("Connection", "close"); // 避免 Keep-Alive 造成部分閘道器逾時
// 3. 準備資料並寫入 Content-Length
byte[] postData = requestString.getBytes("UTF-8"); // 建議明確指定編碼
conn.setRequestProperty("Content-Length", String.valueOf(postData.length));
// 4. 開啟輸出串流並送出資料
out = conn.openOutputStream();
out.write(postData);
out.flush();
// 5. 讀取回應碼與內容
int rc = conn.getResponseCode();
if (rc == HttpConnection.HTTP_OK) {
InputStream in = conn.openInputStream();
// 處理回應資料...
in.close();
}
} catch (IOException e) {
// 網路錯誤處理
} finally {
if (out != null) try { out.close(); } catch (IOException ignored) {}
if (conn != null) try { conn.close(); } catch (IOException ignored) {}
}
| 標頭 | 用途 | 缺失後果 |
|---|---|---|
Content-Type | 告知伺服器請求主體格式 (如 application/x-www-form-urlencoded) | 伺服器無法解析參數,導致 request.getParameter() 全為 null |
Content-Length | 宣告主體位元組長度 | 部分 Servlet 容器會拒絕無長度的 POST,回傳 411 Length Required |
切記:setRequestProperty("Content-Length", ...) 必須在 openOutputStream() 之前 呼叫,否則會拋出 IllegalStateException。
getBytes("UTF-8")、伺服器端 request.setCharacterEncoding("UTF-8") 必須一致,避免中文亂碼。Thread 或使用 TimerTask,否則裝置會凍結。conn.close() 強制中斷。HttpConnection 不會自動跟隨 301/302,需手動讀取 Location 標頭再發新請求。若需上傳二進位檔案,需組裝 multipart/form-data 主體,範例結構:
--boundary_12345
Content-Disposition: form-data; name="file"; filename="photo.jpg"
Content-Type: image/jpeg
[二進位資料]
--boundary_12345--
此時 Content-Type 應設為 multipart/form-data; boundary=boundary_12345,並逐段寫入 OutputStream。