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. exkmp略解

    推导 ext[i]表示母串s[i..lens]和子串t[1..lent]的最长公共前缀. nxt[i]表示t[i..lent]和t[1..lent]的最长公共前缀. 假设ext[1..k]已经算好,现 ...

  2. Careercup - Microsoft面试题 - 24313662

    2014-05-12 07:27 题目链接 原题: Convert a number to a number 题目:把二进制数转化成四进制数. 解法:四是二的倍数,所以两位变一位就可以了. 代码: / ...

  3. IOS开发学习笔记030-xib实现淘宝界面

    使用xib文件实现界面,然后通过模型更新数据. 1.使得控制器继承自UITableViewController 2.创建xib文件,实现界面如下:一个UIImageView,两个lable 3.新建一 ...

  4. jeakins+maven+jmeter构建性能测试自动化( 在eclipse里运行如果出现没有找到“*.loadtest.xls”,请将此文件名修改为你对应使用的xsl文件名)

    背景: 首先用jmeter录制或者书写性能测试的脚本,用maven添加相关依赖,把性能测试的代码提交到github,在jenkins配置git下载性能测试的代码,配置运行脚本和测试报告,配置运行失败自 ...

  5. 使用shell脚本生成数据库markdown文档

    学习shell脚本编程的一次实践,通过shell脚本生成数据库的markdown文档,代码如下: HOST=xxxxxx PORT=xxxx USER="xxxxx" PASSWO ...

  6. windows批处理 打开exe后关闭cmd

    start "" "程序路径.exe"    这样调用就OK啦.如: start "" "D:\123.exe" 如果下 ...

  7. java 二叉树递归遍历算法

    //递归中序遍历 public void inorder() { System.out.print("binaryTree递归中序遍历:"); inorderTraverseRec ...

  8. JavaScript: 理解对象

    ECMA-262 把对象定义为:“无序属性的集合,其属性可以包含基本值.对象或者函数.” 严格来讲,这就相当于说对象是一组没有特定顺序的值.对象的每个属性或者方法都有一个名字,而每个名字都映射到一个值 ...

  9. Ansible实战之Nginx高可用代理LNMP-wordpress

    author:JevonWei 版权声明:原创作品 blog:http://119.23.52.191/ --- 实验环境:前端使用Nginx做代理服务器,静态资源经由缓存服务器,连接后端web集群, ...

  10. 求中位数为K的区间的数目

    给定一个长为 $n$ 的序列和常数 $k$,求此序列的中位数为 $k$ 的区间的数量.一个长为 $m$ 的序列的中位数定义为将此序列从小到大排序后第 $\lceil m / 2 \rceil$ 个数. ...