文件分段请求

最近下载视频遇到限速,限到无法忍受

观察了一下:

1.下载前请求文件所有备份地址,能断点续传

2.单独请求这个地址也会有一定的限速,但好过直接从应用里请求时的速度,差不多高10-20倍

3.使用提速机会时随机生成token

4.客户端定时发送请求,提速机会完成时,请求结果变化然后恢复限速

突破点其实很多,为了顺便实践下iOS上文件下载的管理,定了这么一个方案:

根据本地带宽和限速信息,生成多个请求,从不同的range开始下载,下载完成后合并文件


延期的工程

但结果有点不尽人意:第三方下载器直接下载资源地址也经常停滞,下载速度为0。于是这套方案近期不再维护,等做完第二版的应用再来做一个真正的分段下载器,做点记录:

工程基于AFNetworking3.0+开发,省去了对请求头、响应报文的一些处理

1.发一起一个breakertask(自定义名称)进行下载

2.开始下载,task请求文件总大小。

2-1)拓展:目前通过发起完整请求,progress获取后取消请求来处理,是否有更好的方式

2-2)拓展:目前在下载方法调用时请求,如果在初始化时请求,考虑下载方法调用a与请求文件总大小b的时机,a调用时b在执行中则需要记录a已经调用过并在b完成后真正开始a。

3.再根据传入的带宽和限速信息,计算适当的请求数,发起urlsessiondownloadtask

3-1).发起urlsessiondownloadtask:1)构造NSURLRequest,加入range信息2.生成downloadtask,记录相关信息:请求过程、请求结果、临时存储地址

3-2)拓展:目前主动计算请求数,可以计算过程抽取作为智能分配任务逻辑

3-3)  拓展:目前所有请求直接发起,可以创建待发起请求队列,设置最大并发请求

4.urlsessiondownloadtask更新时汇总progress

4-1)拓展:目前监听task的progress新、旧值,有没有更好的方法,或者考虑直接监听task的变化放弃AFNetworking的progress的处理

5.urlsessiondownloadtask结束时通知需要更新文件

5-1)拓展:失败时加入重连机制

6.按序拼接文件
6-1)完善:判断是否为最后一次文件拼接,如果是调用任务结束回调

6-2)拓展:删除临时文件

7.完善:

1)加入暂停功能

2)调试进入app后台时的请求

3)breakertask的管理器考虑对多个task进行管理,但基于目前的自动分配任务,不会并发多个breakertask,但需要自动进行下个breakertask
breakertask

6-2)完善:判断是否为最后一次文件拼接,如果是调用任务结束回调

p.s. 

还是贴个代码吧,说不定有人需要 点击打开链接
Spring Boot 中处理视频分段请求通常是为了实现实时流媒体传输或者大文件的断点续传功能。当用户需要下载或播放非常大的视频文件时,一次性发送整个文件可能会导致网络压力过大或者加载速度慢。因此,可以将视频拆分成多个小的部分(例如每部分10MB或20MB),通过HTTP Range头来指定请求范围,只发送客户端已经请求过的那段内容。 以下是处理视频分段请求的基本步骤: 1. **设置响应头**:在Spring Boot控制器方法中,通过` ResponseEntity`返回视频资源,设置Content-Disposition头指示这是个可下载的文件,并设置`Accept-Ranges`头为"bytes",表示支持字节范围请求。 ```java @GetMapping("/video") public ResponseEntity<StreamingResponseBody> serveVideo() { HttpHeaders headers = new HttpHeaders(); headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=video.mp4"); headers.setAcceptRanges("bytes"); // 使用StreamingResponseBody包装视频流 return ResponseEntity.ok() .headers(headers) .contentType(MediaType.APPLICATION_OCTET_STREAM) .range(0, videoLengthInBytes - 1); // 根据视频长度提供范围 } ``` 2. **处理Range请求**:如果接收到包含Range头的请求,解析出开始和结束的字节位置,然后从视频流中截取相应部分返回。 ```java @GetMapping("/video/{offset}-{length}") public ResponseEntity<byte[]> serveVideoRange(@PathVariable Long offset, @PathVariable Long length) { long totalSize = getTotalVideoSize(); // 获取视频总大小 if (offset + length > totalSize) { // 检查范围是否合法 throw new ResourceNotFoundException("Invalid range specified."); } byte[] segment = ... // 从视频源读取并截取指定范围的数据 HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.setETagcalculateSegmentHash(segment)); // 可选,计算哈希用于缓存控制 responseHeaders.setContentLength(length); responseHeaders.setRange(new HttpRange(offset, length - 1)); return ResponseEntity.ok().headers(responseHeaders).body(segment); } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值