基於 HttpURLConnection 的網路開發總結
阿新 • • 發佈:2020-11-03
1.HttpURLConnection 上傳進度
用HttpURLConnection 做檔案上傳,會有需要顯示上傳進度的需求。但是根據官方的文件說明,如下圖,HttpURLConnection 在上傳資料之前,預設會強制先將請求體快取在記憶體中。這樣會導致我們上傳進度顯示不準確。具體現象就是上傳進度早早顯示上傳完成,但是上傳網路請求還遲遲未結束。
至於解決方式,上面圖片中前一句官方給出答案,可以呼叫setFixedLengthStreamingMode方法或者setChunkedStreamingMode 方法去禁用掉HttpURLConnection 的上傳快取,這樣進度就顯示正確。
publicvoid setFixedLengthStreamingMode (int contentLength) public void setChunkedStreamingMode (int chunklen)
但是setChunkedStreamingMode 方法並不是被所有伺服器都支援,所以我們捨棄了這種方式。
處理示例:
int contentLength = 1; int uploadLength = 0; if (listener != null) { contentLength = getContentLength(requestParams, boundary, filePaths);//禁用 HttpURLConnection 上傳快取 connection.setFixedLengthStreamingMode(contentLength); } ...... //在寫入的地方呼叫 out.write(bytes); if (listener != null) { float totalLen = contentLength * 1.0f; uploadLength += bytes.length; int progress = Math.round((uploadLength / totalLen) * 100); listener.onProgress(progress); }
2.HttpURLConnection 接收伺服器返回資料
這裡我們需要考慮的點有以下幾點:
- 資料編碼
- 資料型別
- 資料是否壓縮
1. 資料編碼以及資料型別
使用正確的編碼格式,才能正確接收伺服器返回的資料,否則會出現亂碼的情況。
獲取響應體編碼:
//第一種方式,這種方式或者的是相同field的最後一個值 String contentEncoding = connection.getHeaderField("Content-Type"); //第二種方式,這種方式確認是從response中獲取。遍歷獲得 Map<String, List<String>> headerFields = connection.getHeaderFields();
示例值:Content-Type: text/html;charset=UTF-8
2. 資料是否壓縮
如果伺服器返回的資料是採用了某種壓縮格式後傳輸的,我們直接採用正確的編碼直接從資料流讀取資料,也會產生亂碼。這個時候我們要轉成對應壓縮資料流去讀取。
首先我們先判斷服務返回資料是否採用壓縮:
String contentEncoding = connection.getHeaderField("Content-Encoding"); InputStream inputStream = connection.getInputStream(); // 處理介面返回gzip資料 if (!TextUtils.isEmpty(contentEncoding) && "gzip".equalsIgnoreCase(contentEncoding)) { inputStream = new GZIPInputStream(inputStream); }
示例 Header :Content-Encoding: gzip