Http 檔案上傳進度為什麼不準

MrPeak發表於2016-11-21

做過客戶端檔案上傳的同學會明白,基於HTTP的檔案上傳並沒有看起來那麼簡單。按我過去經驗,至少有兩塊工作會比看上去要麻煩一些,第一個是斷點續傳,第二個是進度展示。斷點續傳想要優化的好要花不少力氣,後面有機會再寫,這篇先看上傳進度的問題。

首先說現象:我們呼叫第三方http framework上傳檔案的時候,都會有API回撥告訴我們上傳的具體進度,這個進度值都是不準的。

比如下面程式碼使用alamofire(使用AFNetworking也一樣)標準API上傳一個圖片到伺服器:

上面的程式碼會上傳一個大約20KB的圖片到目標伺服器,如果執行程式碼,你會發現uploadProgress會在一瞬間到達100%,無論裝置的網路是快還是慢(大小為100KB的圖片也一樣)。我們當然知道一個20KB的圖片不可能瞬間抵達伺服器,那麼這個進度到底準不準,問題在哪呢?

要理解這個uploadProgress的含義,需要理解tcp協議傳送資料的方式,略去一些協議的細節,大致的模型可以用下圖表示:

upload00bbab09ca1e9b

我們的客戶端(TCP的傳送方)會有一個send buffer,這個send buffer會快取等待傳送的資料,alamofire等第三方庫會先將資料持續寫入這個send buffer,每寫一次就會呼叫一次uploadProgress,實際上這時候資料還老老實實待在send buffer當中,並沒有抵達伺服器,所以會有上面一呼叫upload函式進度瞬間到100%的現象,這時候如果你根據progress展示進度條,使用者就會發現進度條瞬間跳到100%,之後一直卡住,直到send buffer當中的資料全部真正抵達Server並被Server Ack之後,才會進入response回撥。

我拿自己的iPhone6測試1MB大小的檔案,alamofire每寫4KB資料會進入一次uploadProgress回撥,一直寫到大概120KB左右才停住,等這120KB傳輸完成之後,再啪啪啪寫入後面的100多KB。

所以根據上面的分析,如果你對檔案上傳不做任何優化,會有兩個奇怪的現象:

  1. 幾十KB的小檔案會在一瞬間progress到100%。
  2. 進度跳到100%之後,會卡住幾秒(時長因網路狀況而異)再進入response回撥。

這種場景當然需要優化,怎麼優化呢?有套路的,用個假的進度條就可以了。

解決方案

先不要管上傳的進度,做個步調優雅的進度動畫,慢慢兒的先滑到50%,看下 if 這時候上傳進度有50%,繼續往前滑到75%,else 沒到50%就繼續等上傳進度,如此往復直達100%。為了避免100%之後還要等最後send buffer清空,可以在99%的位置等一等。這種假進度條的套路在瀏覽器載入網頁的時候也會用到,使用過微信開啟網頁等載入完成的就能明白。這個套路廣泛的應用於無法獲取真實進度,卻不得不給產品經理或者使用者一個交代的場景。

這個上傳進度的坑你踩過沒呢?

課後作業:根據上面的分析,下載的進度準不準呢?

打賞支援我寫出更多好文章,謝謝!

打賞作者

打賞支援我寫出更多好文章,謝謝!

Http 檔案上傳進度為什麼不準

相關文章