I am using Erica Sadun's method of Asynchronous Downloads (link here for the project file: download), however her method does not work with files that have a big size (50 mb or above). If I try to download a file above 50 mb, it will usually crash due to a memory crash. Is there anyway I can tweak this code so that it works with large files as well? Here is the code I have in the DownloadHelper Classes (which is already in the download link):

21

I am using Erica Sadun's method of Asynchronous Downloads (link here for the project file: download), however her method does not work with files that have a big size (50 mb or above). If I try to download a file above 50 mb, it will usually crash due to a memory crash. Is there anyway I can tweak this code so that it works with large files as well? Here is the code I have in the DownloadHelper Classes (which is already in the download link):

.h

@protocolDownloadHelperDelegate<NSObject>@optional-(void) didReceiveData:(NSData*) theData;-(void) didReceiveFilename:(NSString*) aName;-(void) dataDownloadFailed:(NSString*) reason;-(void) dataDownloadAtPercent:(NSNumber*) aPercent;@end@interfaceDownloadHelper:NSObject{NSURLResponse*response;NSMutableData*data;NSString*urlString;NSURLConnection*urlconnection;
id <DownloadHelperDelegate>delegate;
BOOL isDownloading;}@property(retain)NSURLResponse*response;@property(retain)NSURLConnection*urlconnection;@property(retain)NSMutableData*data;@property(retain)NSString*urlString;@property(retain) id delegate;@property(assign) BOOL isDownloading;+(DownloadHelper*) sharedInstance;+(void) download:(NSString*) aURLString;+(void) cancel;@end

.m

#define DELEGATE_CALLBACK(X, Y)if(sharedInstance.delegate&&[sharedInstance.delegate respondsToSelector:@selector(X)])[sharedInstance.delegate performSelector:@selector(X) withObject:Y];#define NUMBER(X)[NSNumber numberWithFloat:X]staticDownloadHelper*sharedInstance = nil;@implementationDownloadHelper@synthesize response;@synthesize data;@synthesizedelegate;@synthesize urlString;@synthesize urlconnection;@synthesize isDownloading;-(void) start
{
self.isDownloading = NO; NSURL *url =[NSURL URLWithString:self.urlString];if(!url){NSString*reason =[NSString stringWithFormat:@"Could not create URL from string %@", self.urlString];
DELEGATE_CALLBACK(dataDownloadFailed:, reason);return;}NSMutableURLRequest*theRequest =[NSMutableURLRequest requestWithURL:url];if(!theRequest){NSString*reason =[NSString stringWithFormat:@"Could not create URL request from string %@", self.urlString];
DELEGATE_CALLBACK(dataDownloadFailed:, reason);return;} self.urlconnection =[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];if(!self.urlconnection){NSString*reason =[NSString stringWithFormat:@"URL connection failed for string %@", self.urlString];
DELEGATE_CALLBACK(dataDownloadFailed:, reason);return;} self.isDownloading = YES;// Create the new data object
self.data =[NSMutableData data];
self.response = nil;[self.urlconnection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];}-(void) cleanup
{
self.data = nil;
self.response = nil;
self.urlconnection = nil;
self.urlString = nil;
self.isDownloading = NO;}-(void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)aResponse
{// store the response information
self.response = aResponse;// Check for bad connectionif([aResponse expectedContentLength]<0){NSString*reason =[NSString stringWithFormat:@"Invalid URL [%@]", self.urlString];
DELEGATE_CALLBACK(dataDownloadFailed:, reason);[connection cancel];[self cleanup];return;}if([aResponse suggestedFilename])
DELEGATE_CALLBACK(didReceiveFilename:,[aResponse suggestedFilename]);}-(void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)theData
{// append the new data and update the delegate[self.data appendData:theData];if(self.response){float expectedLength =[self.response expectedContentLength];float currentLength = self.data.length;float percent = currentLength / expectedLength;
DELEGATE_CALLBACK(dataDownloadAtPercent:, NUMBER(percent));}}-(void)connectionDidFinishLoading:(NSURLConnection*)connection
{// finished downloading the data, cleaning up
self.response = nil;// Delegate is responsible for releasing dataif(self.delegate){NSData*theData =[self.data retain];
DELEGATE_CALLBACK(didReceiveData:, theData);}[self.urlconnection unscheduleFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];[self cleanup];}-(void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
{
self.isDownloading = NO;NSLog(@"Error: Failed connection, %@",[error localizedDescription]);
DELEGATE_CALLBACK(dataDownloadFailed:,@"Failed Connection");[self cleanup];}+(DownloadHelper*) sharedInstance
{if(!sharedInstance) sharedInstance =[[self alloc] init];return sharedInstance;}+(void) download:(NSString*) aURLString
{if(sharedInstance.isDownloading){NSLog(@"Error: Cannot start new download until current download finishes");
DELEGATE_CALLBACK(dataDownloadFailed:,@"");return;} sharedInstance.urlString = aURLString;[sharedInstance start];}+(void) cancel
{if(sharedInstance.isDownloading)[sharedInstance.urlconnection cancel];}@end

And finally this is how I write the file with the two classes above it:

-(void) didReceiveData:(NSData*) theData
{if(![theData writeToFile:self.savePath atomically:YES])[self doLog:@"Error writing data to file"];[theData release];}

If someone could help me out I would be so glad!

Thanks,

Kevin

使用NSOutputStream来实现大文件的存储操作

Replace the in-memory NSData *data with an NSOutputStream *stream. In -start create the stream to append and open it:

stream =[[NSOutputStream alloc] initToFileAtPath:path append:YES];[stream open];

As data comes in, write it to the stream:

NSUInteger left =[theData length];NSUInteger nwr =0;do{
nwr =[stream write:[theData bytes] maxLength:left];if(-1== nwr)break;
left -= nwr;}while(left >0);if(left){NSLog(@"stream error: %@",[stream streamError]);}

When you're done, close the stream:

[stream close];

A better approach would be to add the stream in addition to the data ivar, set the helper as the stream's delegate, buffer incoming data in the data ivar, then dump the data ivar's contents to the helper whenever the stream sends the helper its space-available event and clear it out of the data ivar.

ios大文件存储的更多相关文章

  1. GitLab 之 Git LFS 大文件存储的配置

    转载自:https://cloud.tencent.com/developer/article/1010589 1.Git LFS 介绍 Git 大文件存储(Large File Storage,简称 ...

  2. iOS 大文件断点下载

    iOS 在下载大文件的时候,可能会因为网络或者人为等原因,使得下载中断,那么如何能够进行断点下载呢? // resumeData的文件路径 #define XMGResumeDataFile [[NS ...

  3. mongoDB 大文件存储方案, JS 支持展示

    文件存储 方式分类 传统方式 存储路径 仅存储文件路径, 本质为 字符串 优点: 节省空间 缺点: 不真实存储在数据库, 文件或者数据库发送变动需要修改数据库 存储文件本身 将文件转换成 二进制 存储 ...

  4. mongo 固定集合,大文件存储,简单优化 + 三招解决MongoDB的磁盘IO问题

    1.固定集合 > db.createCollection(, max:});//固定集合 必须 显式创建. 设置capped为true, 集合总大小xxx字节, [集合中json个数max] { ...

  5. iOS大文件分片上传和断点续传

    总结一下大文件分片上传和断点续传的问题.因为文件过大(比如1G以上),必须要考虑上传过程网络中断的情况.http的网络请求中本身就已经具备了分片上传功能,当传输的文件比较大时,http协议自动会将文件 ...

  6. PHP大文件存储示例,各种文件分割和合并(二进制分割与合并)

    最近要对视频进行上传,由于涉及到的视频非常的大,因此采用的是分片上传的格式,下面是一个简单的例子: split.php <?php $i = 0; //分割的块编号 $fp = fopen(&q ...

  7. SQL反模式学习笔记12 存储图片或其他多媒体大文件

    目标:存储图片或其他多媒体大文件 反模式:图片存储在数据库外的文件系统中,数据库表中存储文件的对应的路径和名称. 缺点:     1.文件不支持Delete操作.使用SQL语句删除一条记录时,对应的文 ...

  8. git 管理和存储二进制大文件

    git 管理二进制文件 本文档将逐步带你体验 git 的大文件管理方式. 环境: windows10 64位 cmd git版本: git version 2.18.0.windows.1 创建到推送 ...

  9. Github又悄悄升级了,这次的变化是大文件的存储方式

    目录 简介 LFS和它的安装 LFS的使用 从LFS中删除文件 从LFS中拉取代码 转换历史数据到LFS 总结 简介 github是大家常用的代码管理工具,也被戏称为世界上最大的程序员交友网站,它的每 ...

随机推荐

  1. IOS开发---菜鸟学习之路--(一)

    PS(废话): 看了那么多的博客文章,发现大部分人都一直在强调写技术博客的重要性,索性自己也耐着性子写写看吧. 写博客的重要性之类的说明,我就不做复制黏贴的工作了.因为自己没有写过多少,所也不清楚是不 ...

  2. 使用Jmeter做性能测试

    上周刚刚做完项目的性能测试.今天整理和总结一下,随便分享给大家. 首页呢,测试前,我们是有明确的性能指标的,而且测试环境和数据都已准备好,业务分析.场景分析大家根据自己的项目系统进行分析设计,我们选用 ...

  3. 【转】behave行为树学习使用第一天

    最近在学习使用行为树做AI,决定把学到的贡献出来,抛砖引玉,希望可以认识到更多大牛 -- 首先我们了解下什么是行为树和为什么要使用行为树.   在我们项目中如果需要做一个AI敌人,比如做一个手游 某民 ...

  4. hibernate级联查询映射的两种方式

    Hibernate主要支持两种查询方式:HQL查询和Criteria查询.前者应用较为广发,后者也只是调用封装好的接口. 现在有一个问题,就是实现多表连接查询,且查询结果集不与任何一个实体类对应,怎么 ...

  5. 【bzoj5018】[Snoi2017]英雄联盟 背包dp

    题目描述 正在上大学的小皮球热爱英雄联盟这款游戏,而且打的很菜,被网友们戏称为「小学生」.现在,小皮球终于受不了网友们的嘲讽,决定变强了,他变强的方法就是:买皮肤!小皮球只会玩N个英雄,因此,他也只准 ...

  6. ZOJ 2676 Network Wars(最优比例最小割)

    Network Wars Time Limit: 5 Seconds      Memory Limit: 32768 KB      Special Judge Network of Bytelan ...

  7. [nowcoder_Wannafly挑战赛4_F]线路规划

    [nowcoder_Wannafly挑战赛4_F]线路规划 试题描述 Q国的监察院是一个神秘的组织. 这个组织掌握了整个帝国的地下力量,监察着Q国的每一个人. 监察院一共有 \(N\) 个成员,每一个 ...

  8. linux系统——fread()与read()函数族区别

    fread与read区别: 1,fread是带缓冲的,read不带缓冲. 2,fopen是标准c里定义的,open是POSIX中定义的. 3,fread可以读一个结构.read在linux/unix中 ...

  9. Python之文件操作:文件的读写

    一.open函数:对文件读写之前,需要先打开文件,获取文件句柄 注意:open() file() 尽量使用open(),Python3以后不支持file()了 1.open(file_name[,ac ...

  10. 33个好用的图片轮显 jquery图片轮显

    原文发布时间为:2011-05-28 -- 来源于本人的百度文章 [由搬家工具导入] 我个人还是喜欢 jquery.recycle,比较通用。因为由美工设计好的轮显结构,如果套用下面,就感觉不是很方便 ...