文件下載Content-Length詳解

移動(dòng)開(kāi)發(fā)中,為了減小包體積掉瞳,很多文件都會(huì)通過(guò)云端下發(fā)的方式服務(wù)用戶(hù)毕源。文件下載中浪漠,經(jīng)常會(huì)把Content-Length作為下載進(jìn)度的重要參數(shù),但是不同的服務(wù)器對(duì)待文件請(qǐng)求的方式不一樣霎褐,可能存在Content-Length為-1或不準(zhǔn)確的問(wèn)題址愿,導(dǎo)致下載進(jìn)度不準(zhǔn)確,影響用戶(hù)體驗(yàn)冻璃。

1.什么是Content-Length

在HTTP協(xié)議中响谓,Content-Length用于描述HTTP消息實(shí)體的傳輸長(zhǎng)度the transfer-length of the message-body。在HTTP協(xié)議中省艳,消息實(shí)體長(zhǎng)度和消息實(shí)體的傳輸長(zhǎng)度是有區(qū)別娘纷,比如說(shuō)gzip壓縮下,消息實(shí)體長(zhǎng)度是壓縮前的長(zhǎng)度拍埠,消息實(shí)體的傳輸長(zhǎng)度是gzip壓縮后的長(zhǎng)度失驶。

2.Content-Length為什么不靠譜

下面我們來(lái)分析幾種Content-Length的幾種異常情況:

2.1.gzip壓縮問(wèn)題

引用官方文檔的描述:

By default this implementation of HttpURLConnection requests that servers use gzip compression. Since getContentLength() returns the number of bytes transmitted, you cannot use that method to predict how many bytes can be read from getInputStream(). Instead, read that stream until it is exhausted: when read() returns -1. Gzip compression can be disabled by setting the acceptable encodings in the request header。

在默認(rèn)情況下HttpURLConnection 使用 gzip方式獲取枣购,文件 getContentLength() 這個(gè)方法嬉探,每次read完成后可以獲得,當(dāng)前已經(jīng)傳送了多少數(shù)據(jù)棉圈,而不能用這個(gè)方法獲取需要傳送多少字節(jié)的內(nèi)容涩堤,當(dāng)read() 返回 -1時(shí),讀取完成分瘾。

因此要取得正確的文件長(zhǎng)度胎围,要求http請(qǐng)求不要gzip壓縮。

conn .setRequestProperty("Accept-Encoding", "identity")

2.2.請(qǐng)求頭的問(wèn)題

一般可能是請(qǐng)求頭的問(wèn)題? 導(dǎo)致被服務(wù)器拒絕訪問(wèn)了

conn.setRequestProperty("User-Agent", " Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36")

2.3.服務(wù)器端無(wú)Content-Length

如果服務(wù)端沒(méi)有設(shè)置Content-Length, 那么客戶(hù)端獲取Content-Length時(shí)就是-1

3.http協(xié)議之Content-Length

對(duì)于http的請(qǐng)求返回結(jié)果要進(jìn)行內(nèi)容的長(zhǎng)度校驗(yàn)主要有兩種方式德召,二者互斥使用:

1.客戶(hù)端在http頭(head)加Connection:keep-alive時(shí)白魂,服務(wù)器的response是Transfer-Encoding:chunked的形式,通知頁(yè)面數(shù)據(jù)是否接收完畢上岗,例如長(zhǎng)連接或者程序運(yùn)行中可以動(dòng)態(tài)的輸出內(nèi)容福荸,例如一些運(yùn)算比較復(fù)雜且需要用戶(hù)及時(shí)的得到最新結(jié)果,那就采用chunked編碼將內(nèi)容分塊輸出肴掷。

2.除了如1所述之外的情況一般都是可以獲取到Content-Length的敬锐。

在具體的HTTP交互中,客戶(hù)端是如何獲取消息長(zhǎng)度的呢呆瞻,主要基于以下幾個(gè)規(guī)則:

1台夺、Content-Length如果存在并且有效的話(huà),則必須和消息內(nèi)容的傳輸長(zhǎng)度完全一致痴脾。(經(jīng)過(guò)測(cè)試颤介,如果過(guò)短則會(huì)截?cái)啵^(guò)長(zhǎng)則會(huì)導(dǎo)致超時(shí)。)

2买窟、如果存在Transfer-Encoding(重點(diǎn)是chunked)丰泊,則在header中不能有Content-Length薯定,有也會(huì)被忽視始绍。

3、如果采用短連接话侄,則直接可以通過(guò)服務(wù)器關(guān)閉連接來(lái)確定消息的傳輸長(zhǎng)度亏推。(這個(gè)很容易懂)

結(jié)合HTTP協(xié)議其他的特點(diǎn),比如說(shuō)Http1.1之前的不支持keep alive年堆。那么可以得出以下結(jié)論:

1吞杭、在Http 1.0及之前版本中,content-length字段可有可無(wú)变丧。

2芽狗、在http1.1及之后版本。如果是keep alive痒蓬,則content-length和chunk必然是二選一童擎。若是非keep alive,則和http1.0一樣攻晒。content-length可有可無(wú)

4.如何正確下載文件

引用官方文檔的話(huà):

read that stream until it is exhausted: when read() returns -1

numRead = bis.read(buffer, offset,BUFFER_SIZE - offset);

if (numRead == -1) {

// 已經(jīng)沒(méi)有數(shù)據(jù)了,退出循環(huán)

? ? if (offset > 0) {

? ? ? ? ? ? // buffer未填充滿(mǎn),但已經(jīng)沒(méi)數(shù)據(jù)了指黎,則寫(xiě)入文件

? fileOutputStream.write(buffer, 0, offset);

? ? }

? ? break;

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末硼端,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子给梅,更是在濱河造成了極大的恐慌假丧,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件动羽,死亡現(xiàn)場(chǎng)離奇詭異包帚,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)曹质,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)婴噩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人羽德,你說(shuō)我怎么就攤上這事几莽。” “怎么了宅静?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵章蚣,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng)纤垂,這世上最難降的妖魔是什么矾策? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮峭沦,結(jié)果婚禮上贾虽,老公的妹妹穿的比我還像新娘。我一直安慰自己吼鱼,他們只是感情好蓬豁,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著菇肃,像睡著了一般地粪。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上琐谤,一...
    開(kāi)封第一講書(shū)人閱讀 51,562評(píng)論 1 305
  • 那天蟆技,我揣著相機(jī)與錄音,去河邊找鬼斗忌。 笑死质礼,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的飞蹂。 我是一名探鬼主播几苍,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼陈哑!你這毒婦竟也來(lái)了妻坝?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤惊窖,失蹤者是張志新(化名)和其女友劉穎刽宪,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體界酒,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡圣拄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了毁欣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片庇谆。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖凭疮,靈堂內(nèi)的尸體忽然破棺而出饭耳,到底是詐尸還是另有隱情,我是刑警寧澤执解,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布寞肖,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏新蟆。R本人自食惡果不足惜觅赊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望琼稻。 院中可真熱鬧吮螺,春花似錦、人聲如沸欣簇。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)熊咽。三九已至,卻和暖如春闹丐,著一層夾襖步出監(jiān)牢的瞬間横殴,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工卿拴, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留衫仑,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓堕花,卻偏偏與公主長(zhǎng)得像文狱,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子缘挽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容