下载大文件 - iPhone SDK

2024-02-10

我正在使用 Erica Sadun 的异步下载方法(项目文件的链接位于此处:download http://uhelios.com/downloaderica.zip),但是她的方法不适用于大尺寸(50 mb 或以上)的文件。如果我尝试下载超过 50 MB 的文件,通常会由于内存崩溃而崩溃。无论如何,我可以调整这段代码,以便它也可以处理大文件吗?这是我在 DownloadHelper 类中的代码(已在下载链接中):

.h

@protocol DownloadHelperDelegate <NSObject>
@optional
- (void) didReceiveData: (NSData *) theData;
- (void) didReceiveFilename: (NSString *) aName;
- (void) dataDownloadFailed: (NSString *) reason;
- (void) dataDownloadAtPercent: (NSNumber *) aPercent;
@end

@interface DownloadHelper : 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]

static DownloadHelper *sharedInstance = nil;

@implementation DownloadHelper
@synthesize response;
@synthesize data;
@synthesize delegate;
@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 connection
    if ([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 data
    if (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

最后,这就是我编写带有上面两个类的文件的方式:

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

    [theData release];

}

如果有人能帮助我,我会很高兴!

Thanks,

Kevin


替换内存中的NSData *dataNSOutputStream *stream. In -start创建要附加的流并打开它:

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

当数据进入时,将其写入流:

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]);
}

完成后,关闭流:

[stream close];

更好的方法是除了数据 ivar 之外还添加流,将助手设置为流的委托,在数据 ivar 中缓冲传入数据,然后每当流向助手发送其空间时将数据 ivar 的内容转储到助手 -可用事件并将其从数据 ivar 中清除。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

下载大文件 - iPhone SDK 的相关文章

  • iPhone Core Graphics 子视图的粗虚线

    我有一个UIView在其中我通过覆盖使用 Core Graphics 画了一条线drawRect 该视图还包含一个子视图 该子视图也绘制一条线 然而 虽然两个视图都使用几乎相同的代码 至少出于测试目的 但在它们上绘制的线看起来并不相同 正如
  • 使用多处理和 PySftp 并行下载

    我正在尝试创建一个代码来使用 pysftp 和多处理库下载相同类型的 N 个文件 我做了一个基本的Python训练 得到了一些代码并将它们组合成一个 但我无法让它工作 如果有人帮助我 我将不胜感激 该错误发生在 vFtp close 命令之
  • 如何自定义 NSSlider

    我正在尝试在 Cocoa 中实现一个具有 5 个值的自定义滑块 查看我的演示项目 可以在此处下载 http s000 tinyupload com index php file id 07311576247413689572 http s0
  • iPhone - 创建图像网格列表

    我正在开发一个应用程序 它从网站获取图像并使用网格视图向用户显示 例如Apple的照片应用程序 当您点击图像时 我会推送一个显示图像信息和其他内容的视图控制器 实现这个的更好方法是什么 我想到了自定义 UITableViewCell 我见过
  • 内存耗尽:对于使用 diff 的大文件

    我正在尝试使用两个大文件夹 7GB 创建补丁 我是这样做的 diff Naurbw other folder gt file patch 但也许由于文件大小的原因 补丁没有被创建并给出错误 diff memory exhausted 我尝试
  • 使用 flash/flex 在客户端硬盘上下载/保存/写入文件

    我想知道如何下载 保存 写入文件我的服务器 to a 客户的计算机使用闪光灯或柔性 我正在寻找的示例可以在http www flexdownloads com http www flexdownloads com Sign up Sign
  • 为什么单个 Vec4 乘法会大大减慢我的 ogl es 2 片段着色器的速度?

    我正在为 iOS 设备编写 2D OpenGL 游戏 现在 我正在研究 iPad 第一代 上的性能 该游戏有 ogl 1 1 和 2 0 的代码路径 我可以通过 define 使用 ogl 2 0 时 分析器告诉我 我的渲染器利用率 相当稳
  • 在 UITableviewCell 高度动画的同时动画 CALayer 阴影

    我有一个 UITableView 我正在尝试使用它来展开和折叠beginUpdates and endUpdates方法并在发生时显示阴影 在我的自定义 UITableViewCell 中 我有一个图层 我为其创建阴影layoutSubvi
  • 我可以在 NS_SWIFT_NAME 中使用保留关键字吗?

    我正在尝试使 Objective C 委托协议更漂亮以便在 Swift 中使用 但我在弄清楚如何使用时遇到了一些麻烦NS SWIFT NAME 是否可以使用NS SWIFT NAME指定 Swift 名称中与 Objective C 关键字
  • iPhone,使用 isKindOfClass 是否被认为是不好的做法?

    例如 如果有一个 处理所有 类型的方法 if obj isKindOfClass class1 else if obj isKindOfClass class2 etc 这是不好的做法吗 是否有更简洁的替代方案或更好的方法来构建代码 在运行
  • iOS Swift 检测键盘事件

    我能以某种方式检测来自 iOS 键盘的事件吗 我想检测此类事件UIViewController哪个没有UITextField或任何此类物体 我只有四个圆圈UIView我想在按下键盘上的按钮时将它们涂成不同的颜色 您没有任何对象可以从键盘获取
  • 如何等待 webViewDidFinishLoad 完成

    我有一个初始化 webView 的布尔条件 并在 webViewDidFinishLoad 中加载另一个委托 以便在完成完成后触发 但是 由于布尔值在条件 webViewDidFinishLoad 之前返回 因此页面永远不会完全加载 如何确
  • 对 UIImage 进行方形裁剪,导致图像拉伸

    当尝试执行 UIImage 的中心裁剪时 我得到以下结果 左侧是原始图像640 1136 右边是适合正方形的裁剪图像UIImageView at 320 320 turns to 我对比率元素进行了相当多的修改 以便它可以正确检测要修剪的量
  • iOS:从非图像数据生成图像(Godus,如风景)

    所以看到图像后Godus http www kickstarter com projects 22cans project godus我想知道如何生成简单的 非交互式的 2D 图像 with 不同高度或层数的颜色不同就像下面的图片一样 我只
  • 使用反射的属性类型或类

    我想知道是否可以确定对象属性的类或原始类型 获取所有属性名称和值非常容易 所以答案 https stackoverflow com questions 2299841 objective c introspection reflection
  • 从 NSError 返回 NSString

    我正在使用NSURLRequest我的 iPhone 应用程序中的类 调用它的方法返回一个NSString这对于连接正常时非常有用 但问题是我需要将 NSError 转换为 NSString 以便我可以将其返回或运行一些if 对此的声明 有
  • iPhone SDK - 在后台线程中运行重复进程

    我有一个iPhone我想在其中每隔一段时间在后台执行一个方法的应用程序1第二 所以在我的主线程中 我有以下代码UIViewController viewDidLoad NSTimer timerWithTimeInterval 1 0 ta
  • NSMenuItem、自定义视图和 mouseUp 的奇怪问题:

    我在这里遇到了一个非常非常奇怪的 NSMenu 问题 我使用的大约一半的 NSMenuItems 通过 NSMenuItem 上的 setView 方法具有自定义视图 在此自定义视图中 我实现了 mouseUp 来捕获用户单击菜单项的时间
  • 如何使导航栏透明并淡出,就像 iPhone 中的照片应用程序一样

    我是 iPhone 编程新手 有人可以帮我吗 我想在iPhone中开发一个类似照片应用程序的应用程序 如何使导航栏和工具栏透明并淡出 就像 iPhone 中的照片应用程序一样 感谢你 UINavigationBar继承自UIView 所以你
  • PHP 文件服务脚本:下载不可靠?

    这篇文章最初是关于 ServerFault 的一个问题 https serverfault com questions 131156 user receiving partial downloads https serverfault co

随机推荐

  • 在文档中添加新元素后,jQuery 显示不起作用

    我正在使用 Ajax Request 将元素加载到 div 容器中 默认情况下我隐藏一个输入框 如果用户单击该 div 上的编辑图标 我想显示输入框 这是我的代码 HTML代码 div class container div
  • 如何将mysql结果集分布在4个数组的多维数组中

    我对这个简直要疯了 花了近 4 个小时试图弄清楚 但没有成功 我正在尝试获取 4 个数组的多维数组中的 mysql 查询结果集 因此 如果结果集返回 8 条记录 则该数组将包含 4 个每组 2 条记录的数组 如果结果集返回 20 条记录 则
  • Chrome/Webkit 音频标签错误?

    我正在尝试让 HTML5 的音频标签在 Chrome 中工作 以下代码在 Firefox 中可以完美运行 您知道为什么它在 Webkit 中无法运行吗 我还应该指出 我也用 mp3 尝试过此操作 无论什么格式 每当对音频调用 play 时
  • 快速创建 BouncyCastle SecureRandom 实例是否有问题?

    如所述随机数生成器仅生成一个随机数 https stackoverflow com q 767999 1709587 创建一个新实例通常是不正确的System Random每次你需要另一个随机数时 因为System Random是根据时钟播
  • VSCODE 精确的按键绑定,想知道当前的上下文。怎么做?

    许多插件可以通过未记录的 API 设置自己的特定 上下文 设置上下文 由于文档没有列出这些自定义上下文 因此我不能只查看文档来了解如何以正确的方式配置我自己的键绑定 是否有可能知道当前环境 array 例如 我想使用键盘快捷键 没有鼠标 导
  • 我需要一个 Python 类来跟踪它被实例化的次数

    我需要一个像这样工作的类 gt gt gt a Foo gt gt gt b Foo gt gt gt c Foo gt gt gt c i 3 这是我的尝试 class Foo object i 0 def init self Foo i
  • Visual Basic 2010 HTTP POST 请求

    如何将 POST HTTP 请求发送到服务器 在 Visual Basic 2010 中 然后接收字符串回复 您可以通过 HttpWebRequest 来完成此操作 只需设置HttpWebRequest Method http msdn m
  • 通过字符串从枚举获取 Case

    我寻找一个简单的解决方案来通过字符串获取枚举的情况 有 BackedEnums 例如
  • 如何在向量的每个值之间写入逗号?

    我想将向量导出到文件中 每个值之间用逗号分隔 我尝试过使用paste with sep 但它不起作用 有谁知道为什么 gt x lt rnorm 10 gt paste x sep 1 1 08574649988891 2 95803811
  • C 中如何解析链接宏?

    如果我想使用预处理器 define语句可以轻松定义和计算常量和常用函数 并利用较少的 RAM 开销 与使用const值 但是 我不确定如果同时使用多个宏 它们将如何解决 我正在设计自己的DateTime代码处理 类似于 Linux 时间戳
  • 为 Python 3.x 编译 zbar

    几年前 我花了一些时间寻找一种方法zbar使用 Python 2 7 Windows x64 我发布了这个工作解决方案 如何在 最好是纯 Python 中解码 QR 码图像 https stackoverflow com questions
  • 单击模式框时按钮没有被触发

    Assign a Textbox Value to the modal box on the same page已答复 新问题 为什么当我单击按钮时模式框上的按钮没有被触发 我错过了什么吗 我添加了代码来处理服务器端的点击事件 Protec
  • 如何让元素在容器内浮动

    我想把 container在屏幕中央并制作 图表 float left在 的里面 container 但是使用下面的代码 图表 位于 container 谁能告诉我如何更改代码 并告诉我为什么代码将 图表 放在 container cont
  • 什么是 virtualenv,为什么我应该使用它?

    我正在尝试使用此命令安装 Python 包 pip install
  • 如何使用selenium java在mozilla firefox上使用假网络摄像头

    我正在尝试自动化一个包含网络摄像头流的网站 为了使其自动化 我需要某种方法来伪造网络摄像头 我知道这个选项 use fake device for media stream在 Chrome 中模拟网络摄像头 这在 Chrome 中对我有用
  • jqGrid 和动态分组

    我正在对 jqGrid 进行一些动态分组 按照以下位置发布的示例 http www trirand com blog jqgrid jqgrid html http www trirand com blog jqgrid jqgrid ht
  • 服务器是否可以同时收到两个请求? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我对服务器如何处理数千个请求有点困惑 我想如果有数千个请求 最终其中两个请求必须同时到达服务器 如果两条消息同时到达它 它只能处理一条 对
  • PHP:使用 preg_match 获取 url 变量?

    http www example com id 05 or http www example com id 05 name johnny 这是一个字符串 我想得到的值 id从中 它的正确模式是什么 您不需要正则表达式 除非您有充分的理由 否
  • 防止 HttpClient 4 遵循重定向

    我正在使用 Apache HttpComponents 库连接到我的 AppEngine 应用程序 为了对我的用户进行身份验证 我需要将身份验证令牌传递到应用程序的登录地址 http myapp appspot com ah login a
  • 下载大文件 - iPhone SDK

    我正在使用 Erica Sadun 的异步下载方法 项目文件的链接位于此处 download http uhelios com downloaderica zip 但是她的方法不适用于大尺寸 50 mb 或以上 的文件 如果我尝试下载超过