IOS 下载文件断点续传原理与实现(附源码) 文件断点续传原理与实现...

文件断点续传原理与实现

在网络状况不好的情况下,对于文件的传输,我们希望能够支持可以每次传部分数据。首先从文件传输协议FTP和TFTP开始分析,

FTP是基于TCP的,一般情况下建立两个连接,一个负责指令,一个负责数据;而TFTP是基于UDP的,由于UDP传输是不可靠的,虽然传输速度很快,但对于普通的文件像PDF这种,少了一个字节都不行。本次以IM中的文件下载场景为例,解析基于TCP的文件断点续传的原理,并用代码实现。

什么是断点续传?

断点续传其实正如字面意思,就是在下载的断开点继续开始传输,不用再从头开始。所以理解断点续传的核心后,发现其实和很简单,关键就在于对传输中断点的把握,我就自己的理解画了一个简单的示意图:

IOS 下载文件断点续传原理与实现(附源码)
文件断点续传原理与实现...

原理:

断点续传的关键是断点,所以在制定传输协议的时候要设计好,如上图,我自定义了一个交互协议,每次下载请求都会带上下载的起始点,这样就可以支持从断点下载了,其实HTTP里的断点续传也是这个原理,在HTTP的头里有个可选的字段RANGE,表示下载的范围

下面以IOS 开发为例


NSUrlConnection实现断点续传的关键是自定义http request的头部的range域属性。
 Range头域
  Range头域可以请求实体的一个或者多个子范围。例如,
  表示头500个字节:bytes=0-499
  表示第二个500字节:bytes=500-999
  表示最后500个字节:bytes=-500
  表示500字节以后的范围:bytes=500-
  第一个和最后一个字节:bytes=0-0,-1
  同时指定几个范围:bytes=500-600,601-999
  但是服务器可以忽略此请求头,如果无条件GET包含Range请求头,响应会以状态码206(PartialContent)返回而不是以200(OK)。


在ios中使用NSMutableURLRequest来定义头部域

  1. NSURL*url1=[NSURLURLWithString:@"下载地址";
  2. NSMutableURLRequest*request1=[NSMutableURLRequestrequestWithURL:url1];
  3. [request1setValue:@"bytes=20000-"forHTTPHeaderField:@"Range"];
  4. [request1setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
  5. NSData*returnData1=[NSURLConnectionsendSynchronousRequest:request1returningResponse:nilerror:nil];
  6. [selfwriteToFile:returnData1fileName:@"SOMEPATH"];
  7. -(void)writeToFile:(NSData*)datafileName:(NSString*)fileName
  8. {
  9. NSString*filePath=[NSStringstringWithFormat:@"%@",fileName];
  10. if([[NSFileManagerdefaultManager]fileExistsAtPath:filePath]==NO){
  11. NSLog(@"filenotexist,createit...");
  12. [[NSFileManagerdefaultManager]createFileAtPath:filePathcontents:nilattributes:nil];
  13. }else{
  14. NSLog(@"fileexist!!!");
  15. }
  16. FILE*file=fopen([fileNameUTF8String],[@"ab+"UTF8String]);
  17. if(file!=NULL){
  18. fseek(file,0,SEEK_END);
  19. }
  20. intreadSize=[datalength];
  21. fwrite((constvoid*)[databytes],readSize,1,file);
  22. fclose(file);
  23. }
git代码连接:

https://github.com/leechance/BreakPointsDownload

在网络状况不好的情况下,对于文件的传输,我们希望能够支持可以每次传部分数据。首先从文件传输协议FTP和TFTP开始分析,

FTP是基于TCP的,一般情况下建立两个连接,一个负责指令,一个负责数据;而TFTP是基于UDP的,由于UDP传输是不可靠的,虽然传输速度很快,但对于普通的文件像PDF这种,少了一个字节都不行。本次以IM中的文件下载场景为例,解析基于TCP的文件断点续传的原理,并用代码实现。

什么是断点续传?

断点续传其实正如字面意思,就是在下载的断开点继续开始传输,不用再从头开始。所以理解断点续传的核心后,发现其实和很简单,关键就在于对传输中断点的把握,我就自己的理解画了一个简单的示意图:

IOS 下载文件断点续传原理与实现(附源码)
文件断点续传原理与实现...

原理:

断点续传的关键是断点,所以在制定传输协议的时候要设计好,如上图,我自定义了一个交互协议,每次下载请求都会带上下载的起始点,这样就可以支持从断点下载了,其实HTTP里的断点续传也是这个原理,在HTTP的头里有个可选的字段RANGE,表示下载的范围

下面以IOS 开发为例


NSUrlConnection实现断点续传的关键是自定义http request的头部的range域属性。
 Range头域
  Range头域可以请求实体的一个或者多个子范围。例如,
  表示头500个字节:bytes=0-499
  表示第二个500字节:bytes=500-999
  表示最后500个字节:bytes=-500
  表示500字节以后的范围:bytes=500-
  第一个和最后一个字节:bytes=0-0,-1
  同时指定几个范围:bytes=500-600,601-999
  但是服务器可以忽略此请求头,如果无条件GET包含Range请求头,响应会以状态码206(PartialContent)返回而不是以200(OK)。


在ios中使用NSMutableURLRequest来定义头部域

  1. NSURL*url1=[NSURLURLWithString:@"下载地址";
  2. NSMutableURLRequest*request1=[NSMutableURLRequestrequestWithURL:url1];
  3. [request1setValue:@"bytes=20000-"forHTTPHeaderField:@"Range"];
  4. [request1setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
  5. NSData*returnData1=[NSURLConnectionsendSynchronousRequest:request1returningResponse:nilerror:nil];
  6. [selfwriteToFile:returnData1fileName:@"SOMEPATH"];
  7. -(void)writeToFile:(NSData*)datafileName:(NSString*)fileName
  8. {
  9. NSString*filePath=[NSStringstringWithFormat:@"%@",fileName];
  10. if([[NSFileManagerdefaultManager]fileExistsAtPath:filePath]==NO){
  11. NSLog(@"filenotexist,createit...");
  12. [[NSFileManagerdefaultManager]createFileAtPath:filePathcontents:nilattributes:nil];
  13. }else{
  14. NSLog(@"fileexist!!!");
  15. }
  16. FILE*file=fopen([fileNameUTF8String],[@"ab+"UTF8String]);
  17. if(file!=NULL){
  18. fseek(file,0,SEEK_END);
  19. }
  20. intreadSize=[datalength];
  21. fwrite((constvoid*)[databytes],readSize,1,file);
  22. fclose(file);
  23. }
git代码连接:

https://github.com/leechance/BreakPointsDownload