AZ_大文件处理,文件的压缩和解压缩

5.0 大文件的下载

(1)实现思路

边接收数据边写文件以解决内存越来越大的问题

(2)核心代码


//当接收到服务器响应的时候调用,该方法只会调用一次
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    //0.获得当前要下载文件的总大小(通过响应头得到)
    NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;
    self.totalLength = res.expectedContentLength;
    NSLog(@"%zd",self.totalLength);

    //创建一个新的文件,用来当接收到服务器返回数据的时候往该文件中写入数据
    //1.获取文件管理者
    NSFileManager *manager = [NSFileManager defaultManager];

    //2.拼接文件的全路径
    //caches文件夹路径
    NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];

    NSString *fullPath = [caches stringByAppendingPathComponent:res.suggestedFilename];
    self.fullPath  = fullPath;
    //3.创建一个空的文件
    [manager createFileAtPath:fullPath contents:nil attributes:nil];

}
//当接收到服务器返回的数据时会调用
//该方法可能会被调用多次
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{

    //1.创建一个用来向文件中写数据的文件句柄
    //注意当下载完成之后,该文件句柄需要关闭,调用closeFile方法
    NSFileHandle *handle = [NSFileHandle fileHandleForWritingAtPath:self.fullPath];

    //2.设置写数据的位置(追加)
    [handle seekToEndOfFile];

    //3.写数据
    [handle writeData:data];

    //4.计算当前文件的下载进度
    self.currentLength += data.length;

    NSLog(@"%f",1.0* self.currentLength/self.totalLength);
    self.progressView.progress = 1.0* self.currentLength/self.totalLength;
}
6.0 大文件断点下载

(1)实现思路

在下载文件的时候不再是整块的从头开始下载,而是看当前文件已经下载到哪个地方,然后从该地方接着往后面下载。可以通过在请求对象中设置请求头实现。

(2)解决方案(设置请求头)

//2.创建请求对象
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

    //2.1 设置下载文件的某一部分
    // 只要设置HTTP请求头的Range属性, 就可以实现从指定位置开始下载
    /*
     表示头500个字节:Range: bytes=0-499
     表示第二个500字节:Range: bytes=500-999
     表示最后500个字节:Range: bytes=-500
     表示500字节以后的范围:Range: bytes=500-
     */
    NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentLength];
    [request setValue:range forHTTPHeaderField:@"Range"];

(3)注意点(下载进度并判断是否需要重新创建文件)

//获得当前要下载文件的总大小(通过响应头得到)
    NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;

    //注意点:res.expectedContentLength获得是本次请求要下载的文件的大小(并非是完整的文件的大小)
    //因此:文件的总大小 == 本次要下载的文件大小+已经下载的文件的大小
    self.totalLength = res.expectedContentLength + self.currentLength;

    NSLog(@"----------------------------%zd",self.totalLength);

    //0 判断当前是否已经下载过,如果当前文件已经存在,那么直接返回
    if (self.currentLength >0) {
        return;
    }
7.0 输出流

(1)使用输出流也可以实现和NSFileHandle相同的功能

(2)如何使用

    //1.创建一个数据输出流
    /*
     第一个参数:二进制的流数据要写入到哪里
     第二个参数:采用什么样的方式写入流数据,如果YES则表示追加,如果是NO则表示覆盖
     */
    NSOutputStream *stream = [NSOutputStream outputStreamToFileAtPath:fullPath append:YES];

    //只要调用了该方法就会往文件中写数据
    //如果文件不存在,那么会自动的创建一个
    [stream open];
    self.stream = stream;

    //2.当接收到数据的时候写数据
    //使用输出流写数据
    /*
     第一个参数:要写入的二进制数据
     第二个参数:要写入的数据的大小
     */
    [self.stream write:data.bytes maxLength:data.length];

    //3.当文件下载完毕的时候关闭输出流
    //关闭输出流
    [self.stream close];
    self.stream = nil;
8.0 使用多线程下载文件思路
01 开启多条线程,每条线程都只下载文件的一部分(通过设置请求头中的Range来实现)
02 创建一个和需要下载文件大小一致的文件,判断当前是那个线程,根据当前的线程来判断下载的数据应该写入到文件中的哪个位置。(假设开5条线程来下载10M的文件,那么线程1下载0-2M,线程2下载2-4M一次类推,当接收到服务器返回的数据之后应该先判断当前线程是哪个线程,假如当前线程是线程2,那么在写数据的时候就从文件的2M位置开始写入)
03 代码相关:使用NSFileHandle这个类的seekToFileOfSet方法,来向文件中特定的位置写入数据。
04 技术相关
    a.每个线程通过设置请求头下载文件中的某一个部分
    b.通过NSFileHandle向文件中的指定位置写数据
9.0 文件的压缩和解压缩

(1)说明

使用ZipArchive来压缩和解压缩文件需要添加依赖库(libz),使用需要包含SSZipArchive文件,如果使用cocoaPoads来安装框架,那么会自动的配置框架的使用环境

(2)相关代码

//压缩文件的第一种方式
/*
 第一个参数:压缩文件要保存的位置
 第二个参数:要压缩哪几个文件
 */
[SSZipArchive createZipFileAtPath:fullpath withFilesAtPaths:arrayM];

//压缩文件的第二种方式
/*
 第一个参数:文件压缩到哪个地方
 第二个参数:要压缩文件的全路径
 */
[SSZipArchive createZipFileAtPath:fullpath withContentsOfDirectory:zipFile];

//如何对压缩文件进行解压
/*
 第一个参数:要解压的文件
 第二个参数:要解压到什么地方
 */
[SSZipArchive unzipFileAtPath:unZipFile toDestination:fullpath];
posted @ 2016-11-16 18:50  azhang_code  阅读(1483)  评论(0编辑  收藏  举报