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. Asp.net自定义控件开发任我行(8)-数据集绑定

    摘要 已经有好几天没有写博客了,今天继续,前几天写到了注册自定义事件,今天我们来讲数据集绑定. 先把运行效果截个图给大家看,让大家心里也有个底.(大家要从第一章开始看起,我们每一章都是接着前面没做完的 ...

  2. centOS6.6虚拟机启动后登陆界面无法显示

    1.图一和图二对比就很明显发现,我的登陆界面不见了(突然断电导致不正常关机,造成图形界面桌面崩溃) 2.解决方法:启动按Ctrl+Alt+f2切换进命令行界面,root账号进入,重新下载图形界面

  3. python-day5-装饰器第二弹之多层装饰器

    多层装饰器 #首先我们先实现一个简单的登陆与权限验证功能,注意看执行结果 USER_INFO = {} def check_login(func): def inner(*args,**kwargs) ...

  4. 编写高性能React组件-传值篇

    很多人在写React组件的时候没有太在意React组件的性能,使得React做了很多不必要的render,现在我就说说该怎么来编写搞性能的React组件. 首先我们来看一下下面两个组件 import ...

  5. CentOS6.5 安装中文输入法

    直接转载他人文章:http://hi.baidu.com/dxqt58592/item/a85b96e72c423cc0baf37d3c centos 6.5使用yum安装中文输入法 1.需要root ...

  6. Linux下如何挂载和卸载硬盘?

    fdisk -l 查看所有被系统识别的磁盘 df -h 查看磁盘占用情况 sudo umount -v /media 卸载挂载点的硬件 df -T 查看所有磁盘的文件系统类型(type) mount ...

  7. 【bzoj4999】This Problem Is Too Simple! 树链剖分+动态开点线段树

    题目描述 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2^31) 表示将i节点的值改为x. 2. Q i j x(0<=x<2^31) ...

  8. GDKOI 游记

    Day 0 坐和谐号去广州 非常奇怪的一点是,每次坐车去广州人都很少,但是坐车回来人都贼多...... 到酒店住下,出去吃完晚饭,lmy开始奶:明天考数据结构啊! zkw:为什么不考AC自动机和插头D ...

  9. BZOJ 3625 [Codeforces Round #250]小朋友和二叉树 ——NTT 多项式求逆 多项式开根

    生成函数又有奇妙的性质. $F(x)=C(x)*F(x)*F(x)+1$ 然后大力解方程,得到一个带根号的式子. 多项式开根有解只与常数项有关. 发现两个解只有一个是成立的. 然后多项式开根.求逆. ...

  10. IPFS

    http://www.r9it.com/20190412/ipfs-private-net.html IPFS指令集中文版(一) https://www.jianshu.com/p/ce74b32d2 ...