国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

視頻播放、斷點(diǎn)續(xù)傳、多線程下載實(shí)現(xiàn)基礎(chǔ):Range

MockingBird / 3952人閱讀

摘要:如獲取字節(jié)的數(shù)據(jù)和到結(jié)尾的數(shù)據(jù)該頭部指定了響應(yīng)的數(shù)據(jù)的內(nèi)容范圍,語(yǔ)法格式如下說(shuō)明數(shù)據(jù)區(qū)間所采用的單位。

實(shí)現(xiàn)一個(gè)視頻播放的功能,以及對(duì)大文件的下載操作等等都避不開(kāi)一個(gè)點(diǎn):獲取文件任意位置的數(shù)據(jù),如果說(shuō)我們單純的通過(guò) echo file-content 的方式只能用于文件下載,如果視頻文件用于播放中,則難以處理,具體表現(xiàn)則為視頻播放的時(shí)候無(wú)法調(diào)整進(jìn)度條,而且如果是視頻網(wǎng)站,對(duì)于視頻只采用放在某個(gè)可以直接訪問(wèn)的目錄上,那么這個(gè)視頻也就相當(dāng)于公開(kāi)了,對(duì)于什么 VIP 什么的也就無(wú)從說(shuō)起,本篇文章將 Range,來(lái)提供視頻播放、斷點(diǎn)續(xù)傳、多線程下載的技術(shù)依賴實(shí)現(xiàn)

Range

HTTP協(xié)議中,支持以 Range 的形式指定獲取資源的特定偏移的數(shù)據(jù),語(yǔ)法格式如下,具體參考 Range: MDN:

</>復(fù)制代碼

  1. Range: =-
  2. Range: =-
  3. Range: =-, -
  4. Range: =-, -, -

只能是 bytes (目前來(lái)說(shuō)),指定單位

一個(gè)整數(shù),表示在特定單位下,范圍的起始值。

一個(gè)整數(shù),表示在特定單位下,范圍的結(jié)束值。這個(gè)值是可選的,如果不存在,表示此范圍一直延伸到文檔結(jié)束。

如: 獲取 0-100 字節(jié)的數(shù)據(jù)和120到結(jié)尾的數(shù)據(jù)

</>復(fù)制代碼

  1. Range: bytes=0-100,120-
Content-Range

該頭部指定了響應(yīng)的數(shù)據(jù)的內(nèi)容范圍,語(yǔ)法格式如下:

</>復(fù)制代碼

  1. Content-Range: -/
  2. Content-Range: -/*
  3. Content-Range: */

說(shuō)明:

數(shù)據(jù)區(qū)間所采用的單位。通常是字節(jié)(bytes)。

一個(gè)整數(shù),表示在給定單位下,區(qū)間的起始值。

一個(gè)整數(shù),表示在給定單位下,區(qū)間的結(jié)束值。

整個(gè)文件的大?。ㄈ绻笮∥粗?jiǎng)t用 "*" 表示)

例如:

</>復(fù)制代碼

  1. Content-Range: bytes 200-1000/67589
多Range響應(yīng)

目測(cè)在網(wǎng)絡(luò)上面的都沒(méi)有說(shuō)到,但是HTTP協(xié)議支持多Range,具體返回內(nèi)容信息格式如下:

</>復(fù)制代碼

  1. GET http://suda.dev.dx/file HTTP/1.1
  2. Host: suda.dev.dx
  3. Connection: keep-alive
  4. Accept-Encoding: identity;q=1, *;q=0
  5. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3679.0 Safari/537.36
  6. Accept: */*
  7. Referer: http://test.dev.dx/video.html
  8. Accept-Language: zh-CN,zh;q=0.9
  9. Cookie: php_session=8eec314af63d994c2eeb1baca7487332
  10. Range: bytes=0-1,2-3
  11. HTTP/1.1 206 Partial Content
  12. Date: Sun, 10 Mar 2019 09:36:59 GMT
  13. Server: Apache/2.4.23 (Win32) OpenSSL/1.0.2j mod_fcgid/2.3.9
  14. X-Powered-By: PHP/7.2.1
  15. Accept-Ranges: bytes
  16. Content-Length: 220
  17. Keep-Alive: timeout=5, max=100
  18. Connection: Keep-Alive
  19. Content-Type: multipart/byteranges; boundary=multiple_range_ss6bBSB6IlLi0YPpP8rK3g==
  20. --multiple_range_ss6bBSB6IlLi0YPpP8rK3g==
  21. Content-Type: video/mp4
  22. Content-Range: bytes 0-1/132006090
  23. <...somedata...>
  24. --multiple_range_ss6bBSB6IlLi0YPpP8rK3g==
  25. Content-Type: video/mp4
  26. Content-Range: bytes 2-3/132006090
  27. <...somedata...>
Accept-Rangs

服務(wù)器響應(yīng),告訴瀏覽器是否支持 Range,

語(yǔ)法:

</>復(fù)制代碼

  1. Accept-Ranges: bytes
  2. Accept-Ranges: none

none
不支持任何范圍請(qǐng)求單位,由于其等同于沒(méi)有返回此頭部,因此很少使用。不過(guò)一些瀏覽器,比如IE9,會(huì)依據(jù)該頭部去禁用或者移除下載管理器的暫停按鈕。

bytes
范圍請(qǐng)求的單位是 bytes (字節(jié))

實(shí)現(xiàn)代碼

本實(shí)現(xiàn)代碼可以簡(jiǎn)單理解為偽代碼,部分依賴沒(méi)有給出,Swoole 環(huán)境下修改一下即可使用。

使用代碼:

</>復(fù)制代碼

  1. onRequest($request, $response);
  2. }
  3. }
依賴代碼:

</>復(fù)制代碼

  1. file = $file instanceof SplFileObject? $file : new SplFileObject($file);
  2. $this->mime = MimeType::getMimeType($this->file->getExtension());
  3. }
  4. /**
  5. * 處理文件請(qǐng)求
  6. *
  7. * @param sudaframeworkRequest $request
  8. * @param sudaframeworkResponse $response
  9. * @return void
  10. */
  11. public function onRequest(Request $request, Response $response)
  12. {
  13. $ranges = $this->getRanges($request);
  14. $response->setHeader("accept-ranges", "bytes");
  15. if ($ranges === false || $request->getMethod() !== "GET") {
  16. $response->status(400);
  17. } elseif ($ranges === null) {
  18. $response->sendFile($this->file->getRealPath());
  19. } elseif (count($ranges) === 1) {
  20. $response->status(206);
  21. $range = $ranges[0];
  22. $response->setHeader("content-type", $this->mime);
  23. $response->setHeader("content-range", $this->getRangeHeader($range));
  24. $this->sendFileByRange($response, $range);
  25. } else {
  26. $response->status(206);
  27. $this->sendMultipleFileByRange($response, $ranges);
  28. }
  29. }
  30. /**
  31. * 發(fā)送多Range
  32. *
  33. * @param sudaframeworkResponse $response
  34. * @param array $ranges
  35. * @return void
  36. */
  37. protected function sendMultipleFileByRange(Response $response, array $ranges)
  38. {
  39. $separates = "multiple_range_".base64_encode(md5(uniqid(), true));
  40. $response->setHeader("content-type", "multipart/byteranges; boundary=".$separates);
  41. foreach ($ranges as $range) {
  42. $response->write("--".$separates."
  43. ");
  44. $this->sendMultipleRangePart($response, $range);
  45. $this->sendFileByRange($response, $range);
  46. $response->write("
  47. ");
  48. }
  49. }
  50. /**
  51. * 發(fā)送范圍數(shù)據(jù)
  52. *
  53. * @param sudaframeworkResponse $response
  54. * @param array $range
  55. * @return void
  56. */
  57. protected function sendFileByRange(Response $response, array $range)
  58. {
  59. $response->write(new DataStream($this->file->getRealPath(), $range["start"], $range["end"] - $range["start"] + 1));
  60. }
  61. /**
  62. * 獲取Range描述
  63. *
  64. * @param sudaframeworkRequest $request
  65. * @return array|bool|null
  66. */
  67. protected function getRanges(Request $request)
  68. {
  69. $ranges = $this->parseRangeHeader($request);
  70. if (is_array($ranges)) {
  71. return $this->parseRanges($ranges);
  72. } elseif ($ranges === false) {
  73. return false;
  74. }
  75. return null;
  76. }
  77. /**
  78. * 寫(xiě)Range頭
  79. *
  80. * @param sudaframeworkResponse $response
  81. * @param array $range
  82. * @return void
  83. */
  84. protected function sendMultipleRangePart(Response $response, array $range)
  85. {
  86. $response->write("Content-Type: ".$this->mime."
  87. ");
  88. $response->write("Content-Range: ".$this->getRangeHeader($range) ."
  89. ");
  90. }
  91. /**
  92. * 生成Range頭
  93. *
  94. * @param array $range
  95. * @return string
  96. */
  97. protected function getRangeHeader(array $range):string
  98. {
  99. return sprintf("bytes %d-%d/%d", $range["start"], $range["end"], $this->file->getSize());
  100. }
  101. /**
  102. * 獲取Range描述
  103. *
  104. * @param sudaframeworkRequest $request
  105. * @return array|bool|null
  106. */
  107. protected function parseRangeHeader(Request $request)
  108. {
  109. $range = $request->getHeader("range", null);
  110. if (is_string($range)) {
  111. $range = trim($range);
  112. if (strpos($range, "bytes=") !== 0) {
  113. return false;
  114. }
  115. $rangesFrom = substr($range, strlen("bytes="));
  116. return explode(",", $rangesFrom);
  117. }
  118. return null;
  119. }
  120. /**
  121. * 處理范圍
  122. *
  123. * @param array $ranges
  124. * @return array|bool
  125. */
  126. protected function parseRanges(array $ranges)
  127. {
  128. $range = [];
  129. foreach ($ranges as $value) {
  130. if (($r = $this->parseRange($value)) !== null) {
  131. $range[] = $r;
  132. } else {
  133. return false;
  134. }
  135. }
  136. return $range;
  137. }
  138. /**
  139. * 處理Range
  140. *
  141. * @param string $range
  142. * @return array
  143. */
  144. protected function parseRange(string $range):?array
  145. {
  146. $range = trim($range);
  147. if (strrpos($range, "-") === strlen($range) - 1) {
  148. return [
  149. "start" => intval(
  150. trim($range, "-")),
  151. "end" => $this->file->getSize() - 1,
  152. ];
  153. } elseif (strpos($range, "-") !== false) {
  154. list($start, $end) = explode("-", $range, 2);
  155. return ["start" => intval($start) , "end" => intval($end) ];
  156. }
  157. return null;
  158. }
  159. }
參考文獻(xiàn)

https://tools.ietf.org/html/r...

https://tools.ietf.org/html/r...

https://developer.mozilla.org...

https://developer.mozilla.org...

完整代碼

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/30972.html

相關(guān)文章

  • 練習(xí)項(xiàng)目備選清單

    摘要:練習(xí)項(xiàng)目備選清單文件下載器功能概要設(shè)計(jì)實(shí)現(xiàn)新建下載功能以為基礎(chǔ)給出下載鏈接可以啟動(dòng)下載任務(wù)實(shí)現(xiàn)局域網(wǎng)內(nèi)下載傳輸文件以單線程下載方式實(shí)現(xiàn)附加功能支持?jǐn)帱c(diǎn)續(xù)傳實(shí)現(xiàn)多線程下載實(shí)現(xiàn)下載參考技術(shù)套接字編程多線程編程音視頻播放器功能概要設(shè)計(jì)實(shí)現(xiàn)播放常見(jiàn) 練習(xí)項(xiàng)目備選清單 Utilities 1. 文件下載器 功能概要設(shè)計(jì): 實(shí)現(xiàn)新建下載功能(以ftp為基礎(chǔ)) 給出下載鏈接可以啟動(dòng)下載任務(wù) 實(shí)現(xiàn)局...

    guyan0319 評(píng)論0 收藏0
  • 練習(xí)項(xiàng)目備選清單

    摘要:練習(xí)項(xiàng)目備選清單文件下載器功能概要設(shè)計(jì)實(shí)現(xiàn)新建下載功能以為基礎(chǔ)給出下載鏈接可以啟動(dòng)下載任務(wù)實(shí)現(xiàn)局域網(wǎng)內(nèi)下載傳輸文件以單線程下載方式實(shí)現(xiàn)附加功能支持?jǐn)帱c(diǎn)續(xù)傳實(shí)現(xiàn)多線程下載實(shí)現(xiàn)下載參考技術(shù)套接字編程多線程編程音視頻播放器功能概要設(shè)計(jì)實(shí)現(xiàn)播放常見(jiàn) 練習(xí)項(xiàng)目備選清單 Utilities 1. 文件下載器 功能概要設(shè)計(jì): 實(shí)現(xiàn)新建下載功能(以ftp為基礎(chǔ)) 給出下載鏈接可以啟動(dòng)下載任務(wù) 實(shí)現(xiàn)局...

    peixn 評(píng)論0 收藏0
  • Android Okhttp 斷點(diǎn)續(xù)傳面試解析

    摘要:怎么支持?jǐn)帱c(diǎn)續(xù)傳的協(xié)議中默認(rèn)支持獲取文件的部分內(nèi)容,這其中主要是通過(guò)頭部的兩個(gè)參數(shù)和來(lái)實(shí)現(xiàn)的。我們?cè)谒⒁幌旅嬖囶}的時(shí)候,有時(shí)候會(huì)看到一些大廠會(huì)問(wèn)關(guān)于斷點(diǎn)續(xù)傳的原理,那么今天在這里從 HTTP 斷點(diǎn)續(xù)傳知識(shí)和 Android 中如何實(shí)現(xiàn)斷點(diǎn)續(xù)傳的思路來(lái)做一個(gè)關(guān)于 Android 斷點(diǎn)續(xù)傳原理的總結(jié)。 Http 斷點(diǎn)續(xù)傳知識(shí)點(diǎn) 什么是斷點(diǎn)續(xù)傳 指的是在上傳/下載時(shí),將任務(wù)(一個(gè)文件或壓縮包)人為...

    ACb0y 評(píng)論0 收藏0
  • python初學(xué)——網(wǎng)絡(luò)編程之FTP服務(wù)器支持并發(fā)版本

    摘要:擴(kuò)展支持多用戶并發(fā)訪問(wèn)與線程池。項(xiàng)目請(qǐng)見(jiàn)初學(xué)網(wǎng)絡(luò)編程之服務(wù)器。不允許超過(guò)磁盤(pán)配額。該文件是一個(gè)使用模塊編寫(xiě)的線程池類。這一步就做到了線程池的作用。 對(duì)MYFTP項(xiàng)目進(jìn)行升級(jí)。擴(kuò)展支持多用戶并發(fā)訪問(wèn)與線程池。MYFTP項(xiàng)目請(qǐng)見(jiàn)python初學(xué)——網(wǎng)絡(luò)編程之FTP服務(wù)器。 擴(kuò)展需求 1.在之前開(kāi)發(fā)的FTP基礎(chǔ)上,開(kāi)發(fā)支持多并發(fā)的功能2.不能使用SocketServer模塊,必須自己實(shí)現(xiàn)多線...

    oysun 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<