文件分段请求(二)

NSURLSession断点续传实现
本文详细介绍了一个基于NSURLSession的下载器实现,支持断点续传功能。通过NSURLSessionDownloadTask及resumeData实现下载任务的暂停与恢复,同时介绍了如何管理下载任务、持久化下载进度以及合并下载片段。

上一篇好像过去好久了。。

最近得闲把上篇的下载器写完了,这里简单介绍下

项目地址

VWChaplin

实际上是对NSURLSession的一层包装

1.管理者VWChaplin拥有一个session

2.session创建出的task被管理者产出的下载任务VWChaplinSmile关联

对断点续传的支持,API层的"继续"功能

1.NSURLSessionDownloadTask支持一定的断点续传功能,取消时该任务时会提供用于下次继续的数据resumeData

支持的条件如下:

A download can be resumed only if the following conditions are met:

The resource has not changed since you first requested it

The task is an HTTP or HTTPS GET request

The server provides either the ETag or Last-Modified header (or both) in its response

The server supports byte-range requests

The temporary file hasn’t been deleted by the system in response to disk space pressure

2.主动发起的带有range参数的请求

在任务内通过记录总共的任务量和已完成的任务量,能够得到下次请求的range

3.持久化下载任务

对于app无法继续正常运行时,保留现场,将下载任务和下载文件进行存储

文件相关:

1.一次完整的请求

在下载时使用的NSURLSessionTask是NSURLSessionDownloadTask,获取文件的代理方法为:

-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location

方法说明是代理返回后文件将被删除,因此任务完成后需要主动移动文件到能控制的区域

2.多次继续的请求,获取每次中断请求时已下载文件

每次任务的暂停实际上是进行了取消任务的操作,任务取消是不会执行 说明1)内 的代理方法,那去哪里获取刚刚下载的文件?

线索:任务取消后,既然NSURLSessionDownloadTask能提供resumeData来继续下载,那这次task的下载数据一定是能够获取到的。

观察resumeData:存储resmueData后可以看到resumeData内是一个xml格式的存档,以key-value形式存储的相关信息,可以找到的key如下:

NSURLSessionDownloadURL
NSURLSessionResumeBytesReceived
NSURLSessionResumeCurrentRequest
NSURLSessionResumeEntityTag
NSURLSessionResumeInfoTempFileName
NSURLSessionResumeInfoVersion
NSURLSessionResumeOriginalRequest
根据filename可以从tmp目录下获取到本次下载的文件

3.任务碎片的合并

创建config文件记录了下载的完整流程中产生的所有文件(每次暂停即存储该次产生的文件)

以此合并文件即可

4.文件结构:

Main

=>Tasks=>config+fragments

=>History

=>TaskWrapper Persistence=>config

有待完善:

1.保留现场的时机

2.session与管理者的自定义配置

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); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值