<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          手把手教你 Java 文件斷點(diǎn)下載

          共 11999字,需瀏覽 24分鐘

           ·

          2024-04-01 06:30

          84da072cd0675123dd91fd90da3dd3f6.webp來源:juejin.cn/post/7026372482110079012

          ?? 歡迎加入小哈的星球 ,你將獲得: 專屬的項(xiàng)目實(shí)戰(zhàn) / Java 學(xué)習(xí)路線 / 一對(duì)一提問 / 學(xué)習(xí)打卡 /  贈(zèng)書福利


          全棧前后端分離博客項(xiàng)目 1.0 版本完結(jié)啦,2.0 正在更新中...演示鏈接http://116.62.199.48/ ,全程手摸手,后端 + 前端全棧開發(fā),從 0 到 1 講解每個(gè)功能點(diǎn)開發(fā)步驟,1v1 答疑,直到項(xiàng)目上線。目前已更新了189小節(jié),累計(jì)31w+字,講解圖:1308張,還在持續(xù)爆肝中.. 后續(xù)還會(huì)上新更多項(xiàng)目,目標(biāo)是將Java領(lǐng)域典型的項(xiàng)目都整一波,如秒殺系統(tǒng), 在線商城, IM即時(shí)通訊,Spring Cloud Alibaba 等等,戳我加入學(xué)習(xí),已有850+小伙伴加入(早鳥價(jià)超低)


          e70819dc10f7f43ee728971864f7020f.webp

          • 前言
          • 生產(chǎn)實(shí)戰(zhàn)
          • 服務(wù)端 - 業(yè)務(wù)開發(fā)

          前言

          ?

          互聯(lián)網(wǎng)的連接速度慢且不穩(wěn)定,有可能由于網(wǎng)絡(luò)故障導(dǎo)致斷開連接。

          在客戶端下載一個(gè)大對(duì)象時(shí),因網(wǎng)絡(luò)斷開導(dǎo)致上傳下載失敗的概率就會(huì)變得不可忽視。

          ?

          90efc165e9fc8cdd005a68ccbd20168b.webp圖片

          客戶端在GET對(duì)象請(qǐng)求時(shí)通過設(shè)置Range頭部來告訴接口服務(wù)需要從什么位置開始輸出對(duì)象的數(shù)據(jù)。

          判斷是否支持?jǐn)帱c(diǎn)下載,根據(jù)文檔:14.35.1 Byte Rangeshttps://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

                
                // 直接判斷是否有 Accept-Ranges = bytes
          boolean support = urlConnection.getHeaderField("Accept-Ranges").equals("bytes");
          System.out.println("Partial content retrieval support = " + (support ? "Yes" : "No));

          例如:

                
                donald@donald-pro:~$ curl -i --range 0-9 http://localhost:8080/file/chunk/download
          HTTP/1.1 206
          Accept-Ranges: bytes
          Content-Disposition: inline;filename=pom.xml
          Content-Range: bytes 0-9/13485
          Content-Length: 10
          Date: Mon, 01 Nov 2021 09:53:25 GMT

          直接判斷頭部 HEAD,例如:

          ?

          HeadObject 接口用于獲取某個(gè)文件(Object)的元信息。使用此接口不會(huì)返回文件內(nèi)容。

          ?

                
                HEAD /ObjectName HTTP/1.1
          Host: BucketName.oss-cn-hangzhou.aliyuncs.com
          Date: GMT Date
          Authorization: SignatureValue

          需知,對(duì)應(yīng) HTTP 狀態(tài)碼:

          • 206 Partial ContentHTTP Range 請(qǐng)求成功
          • 416 Requested Range Not Satisfiable statusHTTP Range 請(qǐng)求超出界限
          • 200 OK:不支持范圍請(qǐng)求

          小結(jié)如下:

          1. HTTP 范圍請(qǐng)求:需要 HTTP/1.1 及之上支持,如果雙端某一段低于此版本,則認(rèn)為不支持。
          2. 通過響應(yīng)頭中的 Accept-Ranges 來確定是否支持范圍請(qǐng)求。
          3. 通過在請(qǐng)求頭中添加 Range 這個(gè)請(qǐng)求頭,來指定請(qǐng)求的內(nèi)容實(shí)體的字節(jié)范圍。
          4. 在響應(yīng)頭中,通過 Content-Range 來標(biāo)識(shí)當(dāng)前返回的內(nèi)容實(shí)體范圍,并使用 Content-Length 來標(biāo)識(shí)當(dāng)前返回的內(nèi)容實(shí)體范圍長(zhǎng)度。
          5. 在請(qǐng)求過程中,可以通過 If-Range 來區(qū)分資源文件是否變動(dòng),它的值來自 ETag 或者 Last-Modifled。如果資源文件有改動(dòng),會(huì)重新走下載流程。

          生產(chǎn)實(shí)戰(zhàn)

          開發(fā)也得依靠依據(jù),設(shè)定好邊界,才能掌控全局。

          有現(xiàn)成的文檔,來看阿里云文檔https://help.aliyun.com/document_detail/39571.html

          • Range: bytes=0-499:表示第0~499字節(jié)范圍的內(nèi)容。
          • Range: bytes=500-999:表示第500~999字節(jié)范圍的內(nèi)容。
          • Range: bytes=-500:表示最后500字節(jié)的內(nèi)容。
          • Range: bytes=500-:表示從第500字節(jié)開始到文件結(jié)束部分的內(nèi)容。
          • Range: bytes=0-:表示第一個(gè)字節(jié)到最后一個(gè)字節(jié),即完整的文件內(nèi)容。

          HTTP Range 是否合法對(duì)應(yīng)處理:

          • 如果 HTTP Range 請(qǐng)求合法,響應(yīng)返回值為 206 并在響應(yīng)頭中包含 Content-Range
          • 如果 HTTP Range 請(qǐng)求不合法,或者指定范圍不在有效區(qū)間,會(huì)導(dǎo)致 Range 不生效,響應(yīng)返回值為200,并傳送整個(gè) Object 內(nèi)容。

          ?

          如下為 HTTP Range 請(qǐng)求不合法的示例及錯(cuò)誤說明: 假設(shè) Object 資源大小為1000字節(jié),Range 有效區(qū)間為0~999

          • Range: byte=0-499:格式錯(cuò)誤,byte 應(yīng)為 bytes
          • Range: bytes=0-1000:末字節(jié) 1000 超出有效區(qū)間。
          • Range: bytes=1000-2000:指定范圍超出有效區(qū)間。
          • Range: bytes=1000-:首字節(jié)超出有效區(qū)間。
          • Range: bytes=-2000:指定范圍超出有效區(qū)間。

          ?

          舉一些栗子:

                
                # 正常范圍下載
          donald@donald-pro:~$ curl -i --range 0-9 http://localhost:8080/file/chunk/download
          HTTP/1.1 206 
          Accept-Ranges: bytes
          Content-Disposition: inline;filename=Screen_Recording_20211101-162729_Settings.mp4
          Content-Range: bytes 0-9
          Content-Type: application/force-download;charset=UTF-8
          Content-Length: 16241985
          Date: Wed, 03 Nov 2021 09:50:50 GMT

          服務(wù)端 - 業(yè)務(wù)開發(fā)

          這里以 SpringBoot 為栗子:

          1. 對(duì)外支持 range 下載
          2. 底層存儲(chǔ):使用 ceph
          3. Controller 如下:
                
                @Slf4j
          @RestController
          public class Controller {
              @Autowired
              private FileService fileService;
              
              /**
               * 下載文件
               *
               * 對(duì)外提供
               *
               * @param fileId 文件Id
               * @param token token
               * @param accountId 帳號(hào)Id
               * @param response 響應(yīng)
               */
              @GetMapping("/oceanfile/download")
              public void downloadOceanfile(@RequestParam String fileId,
                                            @RequestHeader(value = "Range") String range,
                                            HttpServletResponse response) {

                  this.fileService.downloadFile(fileId, response, range);
              }
          }
          1. Service 如下:
                
                @Slf4j
          @Service
          public class FileService {
              @Autowired
              private CephUtils cephUtils;
              
              /**
               * 直接下載文件
               *
               * Tips: 支持?jǐn)帱c(diǎn)下載
               * @param fileId 文件Id
               * @param response 返回
               * @param range 范圍
               */
              public void downloadFile(String fileId, HttpServletResponse response, String range) {
                  // 根據(jù) fileId 獲取文件信息
                  FileInfo fileInfo = getFileInfo(fileId);

                  String bucketName = fileInfo.getBucketName();
                  String relativePath = fileInfo.getRelativePath();

                  // 處理 range,范圍信息
                  RangeDTO rangeInfo = executeRangeInfo(range, fileInfo.getFileSize());

                  // rangeInfo = null,直接下載整個(gè)文件
                  if (Objects.isNull(rangeInfo)) {
                  
                      cephUtils.downloadFile(response, bucketName, relativePath);
                      return;
                  }
                  // 下載部分文件
                  cephUtils.downloadFileWithRange(response, bucketName, relativePath, rangeInfo);
              }

              private RangeDTO executeRangeInfo(String range, Long fileSize) {

                  if (StringUtils.isEmpty(range) || !range.contains("bytes=") || !range.contains("-")) {

                      return null;
                  }

                  long startByte = 0;
                  long endByte = fileSize - 1;

                  range = range.substring(range.lastIndexOf("=") + 1).trim();
                  String[] ranges = range.split("-");

                  if (ranges.length <= 0 || ranges.length > 2) {

                      return null;
                  }

                  try {
                      if (ranges.length == 1) {
                          if (range.startsWith("-")) {

                              //1. 如:bytes=-1024  從開始字節(jié)到第1024個(gè)字節(jié)的數(shù)據(jù)
                              endByte = Long.parseLong(ranges[0]);
                          } else if (range.endsWith("-")) {

                              //2. 如:bytes=1024-  第1024個(gè)字節(jié)到最后字節(jié)的數(shù)據(jù)
                              startByte = Long.parseLong(ranges[0]);
                          }
                      } else {
                          //3. 如:bytes=1024-2048  第1024個(gè)字節(jié)到2048個(gè)字節(jié)的數(shù)據(jù)
                          startByte = Long.parseLong(ranges[0]);
                          endByte = Long.parseLong(ranges[1]);
                      }
                  } catch (NumberFormatException e) {
                      startByte = 0;
                      endByte = fileSize - 1;
                  }
                  
                  if (startByte >= fileSize) {
                      
                      log.error("range error, startByte >= fileSize. " +
                              "startByte: {}, fileSize: {}", startByte, fileSize);
                      return null;
                  }

                  return new RangeDTO(startByte, endByte);
              }
          }

          以上內(nèi)容,大家可以收藏起來,如果以后遇到這樣的場(chǎng)景,分分鐘搞定!

          ?? 歡迎加入小哈的星球 ,你將獲得: 專屬的項(xiàng)目實(shí)戰(zhàn) / Java 學(xué)習(xí)路線 / 一對(duì)一提問 / 學(xué)習(xí)打卡 /  贈(zèng)書福利


          全棧前后端分離博客項(xiàng)目 1.0 版本完結(jié)啦,2.0 正在更新中...演示鏈接http://116.62.199.48/ ,全程手摸手,后端 + 前端全棧開發(fā),從 0 到 1 講解每個(gè)功能點(diǎn)開發(fā)步驟,1v1 答疑,直到項(xiàng)目上線。目前已更新了189小節(jié),累計(jì)31w+字,講解圖:1308張,還在持續(xù)爆肝中.. 后續(xù)還會(huì)上新更多項(xiàng)目,目標(biāo)是將Java領(lǐng)域典型的項(xiàng)目都整一波,如秒殺系統(tǒng), 在線商城, IM即時(shí)通訊,Spring Cloud Alibaba 等等,戳我加入學(xué)習(xí),已有850+小伙伴加入(早鳥價(jià)超低)


          e70819dc10f7f43ee728971864f7020f.webp


                
                  
                    
                      

          1. 我的私密學(xué)習(xí)小圈子~

          2. 卷翻了,功能強(qiáng)大,企業(yè)級(jí)的微服務(wù)開發(fā)平臺(tái)開源了....

          3. 公司系統(tǒng)太多,能不能實(shí)現(xiàn)賬號(hào)互通?

          4. 談?wù)勡浖_發(fā)模式:瀑布與敏捷

                        

                
                  

          最近面試BAT,整理一份面試資料 Java面試BATJ通關(guān)手冊(cè) ,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。

          獲取方式:點(diǎn)“ 在看 ”,關(guān)注公眾號(hào)并回復(fù)  Java  領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

                  

          PS:因公眾號(hào)平臺(tái)更改了推送規(guī)則,如果不想錯(cuò)過內(nèi)容,記得讀完點(diǎn)一下 在看 ,加個(gè) 星標(biāo) ,這樣每次新文章推送才會(huì)第一時(shí)間出現(xiàn)在你的訂閱列表里。

          點(diǎn)“在看”支持小哈呀,謝謝啦

          瀏覽 26
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人网站在线看 | 国内精品一区二区三区 | 成人毛片网站视频 | 暴操无毛黑丝在线观看 | 无码ww|