MKNetworkKit的断点续传SIDownloader下载

comefrom:http://cache.baiducontent.com/c?m=9f65cb4a8c8507ed4fece763105392230e54f73d6f8b9042238fce0984642c101a39fefd60644d44889622261cf31e1aafad762b2a0322b49bd58b49debe8f2e248230340746c01e4cc75cf28b102a9e79cc0dafea44a7e3e733e3f78995c85422910e446d80819c2a7303be6ee76540f4d5935f142f07ca9c27148e4e012b88574aa14689f7431a10f0f6ca2a4ad45cda&p=8d7fc54ad5c34bf70be2962c444188&newp=9a769a4786cc42af52ad886d15088e231610db2151d6da&user=baidu&fm=sc&query=mknetworkkit+ios+%BA%F3%CC%A8%BC%CC%D0%F8%CF%C2%D4%D8&qid=c53ebf38000a5837&p1=1

https://github.com/MugunthKumar/MKNetworkKit

使用MKNetworkKit

  1. 首先把clone下来的MKNetworkKit文件夹拖进你的项目里面
  2. 到项目里面增加CFNetwork.Framework SystemConfiguration.framework 和 Security.framework.
  3. 把MKNetworkKit.h包含到你的pch文件里面。
  4. 如果是 如果是Mac,删除UIAlertView+MKNetworkKitAdditions.h这个文件

这样,再看看介绍里面的例子。应该就能看懂普通用法了。然后畅快的使用MKNetworkKit库了。

改写目标

上次写的ASIHTTPRequest续传其实已经可以用了。但是为什么需要重新写呢。就是重用!!!

一直都很少自己设计接口什么的。其实只是做了写体力的劳动,把一堆逻辑换成代码给堆了起来。觉得没有人会去重用自己的代码。很少去花心思想怎么样才能写好。

这次改写就只有一个目标,为了更好更多人能使用断点续传来 功能

下载应该在下载继续进行。

保持进度条

每次进入 暂停恢复 可以随时暂停下载

这次改写,这些功能都实现了,啊哈哈哈。

实现

MKNetworkKit库修改

最开始使用MKNetworkKit库做

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {

  NSUInteger size = [self.response expectedContentLength] < 0 ? 0 : [self.response expectedContentLength];
  self.response = (NSHTTPURLResponse*) response;

  // dont‘ save data if the operation was created to download directly to a stream.
  if([self.downloadStreams count] == 0)
    self.mutableData = [NSMutableData dataWithCapacity:size];
  else
    self.mutableData = nil;

  for(NSOutputStream *stream in self.downloadStreams)
    [stream open];

  NSDictionary *httpHeaders = [self.response allHeaderFields];

  // if you attach a stream to the operation, MKNetworkKit will not cache the response.
  // Streams are usually "big data chunks" that doesn‘t need caching anyways.

  if([self.request.HTTPMethod isEqualToString:@"GET"] && [self.downloadStreams count] == 0) {

    // We have all this complicated cache handling since NSURLRequestReloadRevalidatingCacheData is not implemented
    // do cache processing only if the request is a "GET" method
    NSString *lastModified = [httpHeaders objectForKey:@"Last-Modified"];
    NSString *eTag = [httpHeaders objectForKey:@"ETag"];
    NSString *expiresOn = [httpHeaders objectForKey:@"Expires"];

    NSString *contentType = [httpHeaders objectForKey:@"Content-Type"];
    // if contentType is image,

    NSDate *expiresOnDate = nil;

    if([contentType rangeOfString:@"image"].location != NSNotFound) {

      // For images let‘s assume a expiry date of 7 days if there is no eTag or Last Modified.
      if(!eTag && !lastModified)
        expiresOnDate = [[NSDate date] dateByAddingTimeInterval:kMKNetworkKitDefaultImageCacheDuration];
      else
        expiresOnDate = [[NSDate date] dateByAddingTimeInterval:kMKNetworkKitDefaultImageHeadRequestDuration];
    }

    NSString *cacheControl = [httpHeaders objectForKey:@"Cache-Control"]; // max-age, must-revalidate, no-cache
    NSArray *cacheControlEntities = [cacheControl componentsSeparatedByString:@","];

    for(NSString *substring in cacheControlEntities) {

      if([substring rangeOfString:@"max-age"].location != NSNotFound) {

        // do some processing to calculate expiresOn
        NSString *maxAge = nil;
        NSArray *array = [substring componentsSeparatedByString:@"="];
        if([array count] > 1)
          maxAge = [array objectAtIndex:1];

        expiresOnDate = [[NSDate date] dateByAddingTimeInterval:[maxAge intValue]];
      }
      if([substring rangeOfString:@"no-cache"].location != NSNotFound) {

        // Don‘t cache this request
        expiresOnDate = [[NSDate date] dateByAddingTimeInterval:kMKNetworkKitDefaultCacheDuration];
      }
    }

    // if there was a cacheControl entity, we would have a expiresOnDate that is not nil.
    // "Cache-Control" headers take precedence over "Expires" headers

    expiresOn = [expiresOnDate rfc1123String];

    // now remember lastModified, eTag and expires for this request in cache
    if(expiresOn)
      [self.cacheHeaders setObject:expiresOn forKey:@"Expires"];
    if(lastModified)
      [self.cacheHeaders setObject:lastModified forKey:@"Last-Modified"];
    if(eTag)
      [self.cacheHeaders setObject:eTag forKey:@"ETag"];
  }

    if ([self.mutableData length] == 0 || [self.downloadStreams count] > 0) {
        // This is the first batch of data
        // Check for a range header and make changes as neccesary
        NSString *rangeString = [[self request] valueForHTTPHeaderField:@"Range"];
        if ([rangeString hasPrefix:@"bytes="] && [rangeString hasSuffix:@"-"]) {
            NSString *bytesText = [rangeString substringWithRange:NSMakeRange(6, [rangeString length] - 7)];
            self.startPosition = [bytesText integerValue];
            self.downloadedDataSize = self.startPosition;
            DLog(@"Resuming at %d bytes", self.startPosition);
        }
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {

  if([self.downloadStreams count] == 0)
    [self.mutableData appendData:data];

  for(NSOutputStream *stream in self.downloadStreams) {

    if ([stream hasSpaceAvailable]) {
      const uint8_t *dataBuffer = [data bytes];
      [stream write:&dataBuffer[0] maxLength:[data length]];
    }
  }

  self.downloadedDataSize += [data length];

  for(MKNKProgressBlock downloadProgressBlock in self.downloadProgressChangedHandlers) {

    if([self.response expectedContentLength] > 0) {

      double progress = (double)(self.downloadedDataSize) / (double)(self.startPosition + [self.response expectedContentLength]);
      downloadProgressBlock(progress);
    }
  }
}

具体改了哪,忘记了。有心思对照源码看看。应该是属于MKNetworkKit的bug。也不知道新版改过来没有。但是你clone我的demo,这个版本是可以的。

断点 其实我一共就写了两个简单的类而已。

基础的是SIBreakpointsDownload。继承于MKNetworkOperation。判断了续传的位置。

一个SIDownloadManager写成单例,继承于MKNetworkEngine。用来管理多任务 使用的时候就只用SIDownloadManager这个类来添加下载。然后想在 demo地址

[email protected]:iiiyu/SIDownloader.git

其实已经很简单了,照着demo改改就能自己用了。

总结

这次改写以后,代码结构变的很清晰。复杂性和耦合性都有所降低。可用性提高。而且,反正我是没有google到可以直接拿来用的断点ios代码库-www.lanrenios.com

时间: 2024-11-03 22:43:15

MKNetworkKit的断点续传SIDownloader下载的相关文章

断点续传---多线程下载进阶(一)

打算总结7篇笔记,来学习下断点续传---多线程下载进阶 AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="sms.down" android:versionCode="1&quo

ftp和http断点续传及下载delphi实现

ftp和http断点续传及下载delphi实现 转载:http://blog.csdn.net/youthon/article/details/7531211 分类:            Delphi编程网络编程2012-05-03 13:332237人阅读评论(1)收藏举报 delphiintegerstring服务器resturl 接下来我们来写最主要的代码,也就是下载部分了,首先来看HTTP协议的: procedure TForm1.HttpDownLoad(aURL, aFile: s

Android的断点续传的下载在线文件示例

Android的断点续传的下载在线文件示例 文件的结构如下: activity_main.xml: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_h

http文件的断点续传和下载

http://www.tuicool.com/articles/ZbyymqJ Content-Disposition:inline; filename= "c501b_01_h264_sd_960_540.mp4"    浏览器的行为不再是提示下载文件,而是打开文件 一个server端和client端的例子 http抓包的例子 206 Partial Content 服务器已经成功处理了部分 GET 请求.类似于 FlashGet 或者迅雷这类的 HTTP下载工具都是使用此类响应实现

Android 多线程断点续传同时下载多个大文件

最近学习在Android环境中一些网络请求方面的知识,其中有一部分是关于网络下载方面的知识.在这里解析一下自己写的demo,总结一下自己所学的知识.下图为demo的效果图,仿照一些应用下载商城在ListView中列出加载项,然后可以可以下载和停止. 1.概述 这里有几个比较重要的类DownloadManager.DownloadService.DownloadTask.ThreadDAOImpl.主要的下载流程如下. (1) DownloadManager 负责下载任务的调配,以及下载服务Dow

多线程断点续传及下载

断点下载 package com.example.downloaddemo; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import android.os.Bundle; import android.os.Handler; import android.os.

PHP断点续传(下载)代码

<?php /** * PHP-HTTP断点续传实现 * @param string $path: 文件所在路径 * @param string $file: 文件名 * @return void */ function download($path,$file) { $real = $path.'/'.$file; if(!file_exists($real)) { return false; } $size = filesize($real); $size2 = $size-1; $rang

Java--&gt;实现断点续传(下载)

--> 断点续传: 就像迅雷下载文件一样,停止下载或关闭程序,下次下载时是从上次下载的地方开始继续进行,而不是重头开始... --> RandomAccessFile --> pointer(文件指针) --> seek(移动文件指针) --> 断点续传 package com.dragon.java.downloadfile; import java.io.File; import java.io.IOException; import java.io.RandomAcce

AFNetworking断点续传、下载图片

下载图片:下载图片后保存在本地文件中 //在lock和挂起状态都会下载 NSURLRequest *request=[[NSURLRequest alloc]initWithURL:[NSURL URLWithString:@"http://attach.bbs.miui.com/forum/201110/05/082552rm0v11zlv1axd13l.png"]]; //操作配置 AFHTTPRequestOperation *requestOperator=[[AFHTTPRe