ios-断点续传

本文介绍了一种iOS应用中实现断点续传的方法。通过自定义类ResumeDowdload,利用NSURLConnection进行文件下载,并支持暂停与继续功能。文章详细展示了如何设置请求头、处理下载过程中的各种回调及文件读写。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//断点续传

#import "ViewController.h"

#import "ResumeDowdload.h"

@interface ViewController ()
{
    ResumeDowdload *_resume;
    float _pv;
}

@property(nonatomic,weak)IBOutlet UIButton *cancelbutton;

@property(nonatomic,weak)IBOutlet UIButton *continuebutton;

@property(nonatomic,weak)IBOutlet UIImageView *imageView;

@property(nonatomic,weak)IBOutlet UIProgressView *progressView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.imageView.backgroundColor = [UIColor grayColor];
    _pv = 0.0;
    self.progressView.hidden = YES;
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.
}

-(IBAction)downloadStart:(id)sender
{
    //NSString *urlStr = @"http://farm3.staticflickr.com/2846/9823925914_78cd653ac9_b_d.jpg";
    NSString *urlStr = @"http://10.0.166.136/6ca014e5jw1etbxl.png";
    _resume = [[ResumeDowdload alloc]init];
    _resume.fileUrl = urlStr;
    
    _resume.delegate = self;
    
    _resume.updataingMethod =@selector(updataing:);
    _resume.updataingFinishMethod = @selector(updataFinish:);
    _resume.updataingFailMethod = @selector(updataFail:);
    
    //开始下载
    [_resume requestFromUrl];
    self.progressView.hidden = NO;
    self.progressView.progress = _pv;
    
    
}
/**
 *  下载失败
 *
 *  @param rd <#rd description#>
 */
-(void)updataFail:(ResumeDowdload *)rd{
    NSLog(@"文件下载失败:%@",[rd localPath]);
}

/**
 *  下载完成
 *
 *  @param rd <#rd description#>
 */
-(void)updataFinish:(ResumeDowdload *)rd{
    self.progressView.hidden = YES;
    if ([rd localPath]) {
    self.imageView.image = [UIImage imageWithContentsOfFile:rd.localPath];
    }
    NSLog(@"文件下载完成");
}

-(void)updataing:(ResumeDowdload *)rd{
    _pv = [rd.downloadSize longLongValue]/[rd.fileSize longLongValue];
    self.progressView.progress = _pv;
    NSLog(@"进度条:%f",_pv);
}

-(IBAction)downloadStop:(id)sender
{
    if (_resume) {
        [_resume stopDownload];
    }
}

@end

#import <Foundation/Foundation.h>




@interface ResumeDowdload : NSObject<NSURLConnectionDataDelegate>
{
    //网络连接
    NSURLConnection *_httpConnection;
    //文件句柄
    NSFileHandle *_fileHandle;
}

//要下载文件的地址
@property(nonatomic,retain)NSString *fileUrl;

//要下载文件的大小
@property(nonatomic,retain)NSNumber *fileSize;

//已经下载了的大小
@property(nonatomic,retain)NSNumber *downloadSize;

//从指定的网址获取数据
-(void)requestFromUrl;


//代理对象
@property(nonatomic,assign)id delegate;

//更新下载进度的回调方法
@property(nonatomic,assign)SEL updataingMethod;

//更新下载完成的回调方法
@property(nonatomic,assign)SEL updataingFinishMethod;

//更新下载失败的回调方法
@property(nonatomic,assign)SEL updataingFailMethod;

@property(nonatomic,assign)SEL method;


//停止下载
-(void)stopDownload;

//获取当前文件的路径
-(NSString *)localPath;

@end

#import "ResumeDowdload.h"
#import "NSString+MD5Addition.h"

@implementation ResumeDowdload

-(id)init
{
    if (self = [super init]) {
        
    }
    return self;
}

//从指定的网址获取数据
-(void)requestFromUrl
{
    //断点续传请求部分
    
    NSURL *url = [NSURL URLWithString:self.fileUrl];
    //用可变的
    //将网址转换成可变请求对象
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    
    //获取当前下载的大小
    NSString *rangeStr = [NSString stringWithFormat:@"bytes=%lld-",[self.downloadSize longLongValue]];
    //根据当前下载的大小设置请求数据范围
    [request setValue:rangeStr forHTTPHeaderField:@"Range"];
    
    //创建连接
    _httpConnection = [[NSURLConnection alloc]initWithRequest:request delegate:self];
    
     NSLog(@"downloadSize:%@",self.downloadSize);
    
}



//停止下载
-(void)stopDownload
{
    //如果句柄存在 则关闭文件,自行释放 
    if(_fileHandle){
        [_fileHandle closeFile];
        _fileHandle = nil;
    }
    //停止下载
    [_httpConnection cancel];
    //释放对象
    _httpConnection = nil;
}

//获取当前文件的路径
-(NSString *)localPath
{
    //返回当前沙盒的路径
    NSString *path = NSHomeDirectory();
    
    //根据文件的url加密后命名文件名,保证
    NSString *fileName = [self.fileUrl stringFromMD5];
    
    path = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"Documents/%@",fileName]];
 
    return path;
    
    
    
}

#pragma mark -用代理形式异步请求-
//调用它就证明,连接有响应,已经下载完响应头,开始下载
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    
    NSLog(@"%@",NSStringFromSelector(_cmd));
    
    //文件为什么要关闭
    if(_fileHandle){
        [_fileHandle closeFile];
    }
    //获取总文件大小
    self.fileSize = [NSNumber numberWithLongLong :response.expectedContentLength];
    //如果当前不存在文件,则创建一个
    NSFileManager *mg = [NSFileManager defaultManager];
    if (![mg fileExistsAtPath:[self localPath]]) {
        //创建 判断 查找 contents 是指数据 当前没有
        [mg createFileAtPath:[self localPath] contents:nil attributes:nil];
    }
    //获取文件句柄 是更新用的(更具文件路径获取文件句柄,用来操作文件),更新类型的句柄
    _fileHandle = [NSFileHandle fileHandleForUpdatingAtPath:[self localPath]];
    
    
    //将文件指针移动到文件结尾
    [_fileHandle seekToEndOfFile];
    
    
    //设置已经下载文件的大小
    self.downloadSize = [NSNumber numberWithLongLong:[_fileHandle offsetInFile]];
    
     NSLog(@"downloadSize:%@",self.downloadSize);
    /**
     *  要下载之前,先要取到文件的句柄,将文件的句柄移动到末尾,给我们返回当前文件的大小
     */
}
//调用它证明正在接受数据,响应体,根据数据大小,反复不间断的接收
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    //不间断的接受数据
    
    //将接受到的数据写入文件
    [_fileHandle writeData:data];
    
    //计算已经下载的大小   先写入再计算
    unsigned long long newDownloadSize = [self.downloadSize longLongValue] + [data length];
    
    //重新设置已经下载的大小
    
    self.downloadSize = [NSNumber numberWithLongLong:newDownloadSize];
    /**
     *  PS:此时句柄在末尾,写入即追加数据,重新设置已经下载的大小
     */
    NSLog(@"downloadSize:%@",self.downloadSize);
    //需要通知代理进行更新
    //检查代理是否实现了这个方法
    if([self.delegate respondsToSelector:self.updataingMethod])
    {
        
        [self.delegate performSelector:self.updataingMethod withObject:self];
    }
    
    NSLog(@"%s",__func__);
}
//调用它就证明已经下载完毕 下载成功
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    
    //文件下载完成 关闭文件,让Handle 释放(释放对象)
    if(_fileHandle)
    {
        [_fileHandle closeFile];
        _fileHandle = nil;
    }

    if ([self.delegate respondsToSelector:self.updataingFinishMethod]) {
         [self.delegate performSelector:self.updataingMethod withObject:self];
    }
    
    NSLog(@"%s",__func__);
}

//连接发生错误下载失败
//1.断网了
//2.
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"下载失败");
    if ([self.delegate respondsToSelector:self.updataingFailMethod]) {
        [self.delegate performSelector:self.updataingMethod withObject:self];
    }
    
    
    NSLog(@"%s",__func__);
}


@end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值