1. 程式人生 > >java向伺服器post請求時首部欄位content-length的計算方法

java向伺服器post請求時首部欄位content-length的計算方法

當java向伺服器post請求時,首部中有一個Content-length欄位,即請求主體中的位元組數。首部在主體的前面。不過,要寫入首部,需要知道主體的長度,而在寫首部的時候可能還不知道主體的長度。正常情況下,對於這個兩難的問題。
如圖所示
這裡寫圖片描述
Java的解決辦法是:對於從HttpURLConnection獲取的OutputStream ,將寫入此OutputStream的所有內容快取,直到流關閉。此時它就會知道主體中有多少位元組,所以有足夠的資訊來寫入Content-length首部。
這種模式對於響應典型Web表單的短請求很合適。不過,對於非常長的表單或一些SOAP訊息,響應時負擔會很大。用HTTP PUT傳送中等到大型文擋時會很浪費,也很慢。如果Java 通過網路傳送第一位元組之前,不需要等待寫入最後一位元組,將會高效得多。
Java 為這個問題提供了兩種解決方案。
如果你知道資料的大小,例如使用HTTP PUT上傳一個已知大小的檔案,可以將資料的大小告訴HttpURLConnection物件。
如果預先不知道資料大小,可以使用分塊傳輸編碼方式。在分塊傳輸編碼方式中,請求主體以多個部分發送,每個部分都有自己單獨的內容長度。要啟用分塊傳輸編碼方式,只要在連線URL之前將分塊大小傳入setChunkedStreamingMode()方法(需要伺服器支援分塊傳輸編碼方式,所以,,除非確實需要,否則不要使用分塊傳輸編碼方式)。

如果恰好預先知道請求資料的大小,可以將這個資訊提供給HttpURLConnection物件,從而優化連線。如果這樣做,Java會立即通過網路將資料以流方式傳送。否則,它必須快取你寫入的所有資料來確定內容長度,而且只有在你關閉流之後才能通過網路傳送資料。如果知道資料的具體大小,可以將這個數傳遞給setFixedlengthStreamingMode()方法。由於這個數可能實際大於int所能儲存的最大整數(大約21億個位元組,大約200M),所以在Java 7及以後版本中可以使用一個long。
注意兩個問題:
1. Java會在HTTP首部的Content-length欄位中使用這個數。不過,如果接下來試圖寫入的資料多於或少於給出的這個位元組數, Java會丟擲一個IOException異常。
2. 流模式確實會妨礙身份認證和重定向。如果給定的URL要求認證或重定向,就會丟擲一個HttpRetryException異常