zoukankan      html  css  js  c++  java
  • iOS开发网络编程之断点续传-NSURLConnection

    最近在做一个小项目的时候,发现使用NSURLSession或者AFNNetworking进行断点续传时诸多的不便,于是自己封装了一个类来实现断点续传,在程序重新启动时仍然可以继续下载(需自己调用方法),同时可以在同一时间多次调用该类方法。使用时请注意传入各参数的合理性,方法内部并没有对传入的参数进行修正

    主要技术: NSURLConnection、block、NFFileHandle

    1、首先,我提供一个类方法,供外界调用。 创建的类名为DownloadService

     1 //
     2 //  DownloadService.h
     3 //  11111
     4 //
     5 //  Created by Liu Feng on 14-2-17.
     6 //  Copyright (c) 2014年 Liu Feng. All rights reserved.
     7 //
     8 
     9 #import <Foundation/Foundation.h>
    10 
    11 typedef void (^DownloadServiceSuccess)(NSString *savePath);
    12 typedef void (^DownloadServiceFailure)(NSError *error);
    13 
    14 @interface DownloadService : NSObject
    15 /**
    16  *  下载指定URL的资源到路径
    17  *
    18  *  @param urlStr   网络资源路径
    19  *  @param toPath   本地存储文件夹
    20  *  @param capacity 缓存大小,单位为Mb
    21  *  @param success  成功时回传本地存储路径
    22  *  @param failure  失败时回调的错误原因
    23  */
    24 + (void)downLoadWithURL:(NSString *)urlStr toDirectory:(NSString *)toDirectory cacheCapacity:(NSUInteger)capacity  success:(DownloadServiceSuccess)success failure:(DownloadServiceFailure)failure;
    25 
    26 @end

    2、在.m中实现

      1 //
      2 //  DownloadService.m
      3 //  11111
      4 //
      5 //  Created by Liu Feng on 14-2-17.
      6 //  Copyright (c) 2014年 Liu Feng. All rights reserved.
      7 //
      8 
      9 #import "DownloadService.h"
     10 
     11 static DownloadService *_download;
     12 static NSMutableDictionary *_dictPath;
     13 static NSMutableDictionary *_dictBlock;
     14 static NSMutableDictionary *_dictHandle;
     15 static unsigned long long _cacheCapacity; // 缓存
     16 static NSMutableData *_cacheData;
     17 
     18 typedef void (^myBlcok)(NSString *savePath, NSError *error);
     19 
     20 @interface DownloadService ()<NSURLConnectionDataDelegate>
     21 
     22 @end
     23 
     24 @implementation DownloadService
     25 
     26 + (void)initialize
     27 {
     28     _download = [[DownloadService alloc] init];
     29     _dictPath = [NSMutableDictionary dictionary]; // 存储文件路径
     30     _dictBlock = [NSMutableDictionary dictionary]; // 存储block
     31     _dictHandle = [NSMutableDictionary dictionary]; // 存储NSFileHandle对象
     32     _cacheData = [NSMutableData data]; // 存放缓存
     33 }
     34 
     35 + (void)downLoadWithURL:(NSString *)urlStr toDirectory:(NSString *)toDirectory cacheCapacity:(NSInteger)capacity success:(DownloadServiceSuccess)success failure:(DownloadServiceFailure)failure{
     36     
     37     // 1. 创建文件
     38     NSString *fileName = [urlStr lastPathComponent];
     39     NSString *filePath = [NSString stringWithFormat:@"%@/%@", toDirectory, fileName];
     40     
     41     // 记录文件起始位置
     42     unsigned long long from = 0;
     43     if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]){ // 已经存在
     44         from = [[NSData dataWithContentsOfFile:filePath] length];
     45     }else{ // 不存在,直接创建
     46         [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];
     47     }
     48     
     49     // url
     50     NSURL *url = [NSURL URLWithString:urlStr];
     51     
     52     // 请求
     53     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:5.0f];
     54     
     55     // 设置请求头文件
     56     NSString *rangeValue = [NSString stringWithFormat:@"bytes=%llu-", from];
     57     [request addValue:rangeValue forHTTPHeaderField:@"Range"];
     58     
     59     // 创建连接
     60     NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:_download];
     61     
     62     // 保存文章连接
     63     _dictPath[connection.description] = filePath;
     64     
     65     // 保存block,用于回调
     66     myBlcok block = ^(NSString *savePath, NSError *error){
     67         if (error) {
     68             if (failure) {
     69                 failure(error);
     70             }
     71         }else{
     72             if (success) {
     73                 success(savePath);
     74             }
     75         }
     76     };
     77     _dictBlock[connection.description] = block;
     78     
     79     // 保存缓存大小
     80     _cacheCapacity = capacity * 1024 * 1024;
     81     
     82     // 开始连接
     83     [connection start];
     84 }
     85 /**
     86  *  接收到服务器响应
     87  *
     88  *  @param connection 哪一个连接
     89  *  @param response   响应对象
     90  */
     91 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
     92 {
     93     // 取出文章地址
     94     NSString *filePath = _dictPath[connection.description];
     95     
     96     // 打开文件准备输入
     97     NSFileHandle *outFile = [NSFileHandle fileHandleForWritingAtPath:filePath];
     98     
     99     // 保存文件操作对象
    100     _dictHandle[connection.description] = outFile;
    101 }
    102 /**
    103  *  开始接收数据
    104  *
    105  *  @param connection 哪一个连接
    106  *  @param data       二进制数据
    107  */
    108 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    109 {
    110     // 取出文件操作对象
    111     NSFileHandle *outFile = _dictHandle[connection.description];
    112     
    113     // 移动到文件结尾
    114     [outFile seekToEndOfFile];
    115     
    116     // 保存数据
    117     [_cacheData appendData:data];
    118     
    119     if (_cacheData.length >= _cacheCapacity) {
    120         // 写入文件
    121         [outFile writeData:data];
    122         
    123         // 清空数据
    124         [_cacheData setLength:0];
    125     }
    126 }
    127 /**
    128  *  连接出错
    129  *
    130  *  @param connection 哪一个连接出错
    131  *  @param error      错误信息
    132  */
    133 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
    134 {
    135     // 取出文件操作对象
    136     NSFileHandle *outFile = _dictHandle[connection.description];
    137     
    138     // 关闭文件操作
    139     [outFile closeFile];
    140     
    141     // 回调block
    142     myBlcok block = _dictBlock[connection.description];
    143     
    144     if (block) {
    145         block(nil, error);
    146     }
    147     
    148     // 移除字典中
    149     [_dictHandle removeObjectForKey:connection.description];
    150     [_dictPath removeObjectForKey:connection.debugDescription];
    151     [_dictBlock removeObjectForKey:connection.description];
    152 }
    153 /**
    154  *  结束加载
    155  *
    156  *  @param connection 哪一个连接
    157  */
    158 - (void)connectionDidFinishLoading:(NSURLConnection *)connection
    159 {
    160     // 取出文件操作对象
    161     NSFileHandle *outFile = _dictHandle[connection.description];
    162     
    163     // 关闭文件操作
    164     [outFile closeFile];
    165     
    166     // 取出路径
    167     NSString *savePath = [_dictPath objectForKey:connection.description];
    168     
    169     // 取出block
    170     myBlcok block = _dictBlock[connection.description];
    171 
    172     // 回调
    173     if (block) {
    174         block(savePath, nil);
    175     }
    176     
    177     // 移除字典中
    178     [_dictHandle removeObjectForKey:connection.description];
    179     [_dictPath removeObjectForKey:connection.debugDescription];
    180     [_dictBlock removeObjectForKey:connection.description];
    181 }
    182 
    183 
    184 @end
  • 相关阅读:
    jQuery validate 的valid()方法一直返回true
    Webstrom 使用过程中遇到的问题以及解决方案
    CSS选择符 新的认识
    前端常用正则匹配
    魔术师
    node 安装express
    为什么报错说req未定义,createServer只接受匿名函数吗?
    nodejs报错 events.js:72 throw er; // Unhandled 'error' event
    我对 javascript 闭包的理解
    ORM框架,sqlsugar学习一
  • 原文地址:https://www.cnblogs.com/liufeng24/p/3555303.html
Copyright © 2011-2022 走看看