使用 RestKit 下载和保存大文件

Posted

技术标签:

【中文标题】使用 RestKit 下载和保存大文件【英文标题】:Downloading and saving large files with RestKit 【发布时间】:2012-05-22 15:09:29 【问题描述】:

我正在使用 RestKit 在我的应用程序中下载多个文件。只要文件不是太大,一切都像魅力一样。不幸的是,我尝试下载一个大视频文件(大约 230 MB)并得到一个memory warning 并且应用程序崩溃了。

我用下面这行开始下载

[[RKClient sharedClient] get:[NSString stringWithFormat:@"/%@", listItem.filename] delegate:self];

在委托方法中,我将其本地保存在appDirectory/Library/Caches/

- (void)request:(RKRequest *)request didLoadResponse:(RKResponse *)response

    NSURL * url = [NSURL fileURLWithPath:[cacheDirectory stringByAppendingPathComponent:response.URL.lastPathComponent]];

    [[response body] writeToURL:url atomically:YES];

我检查了 Instruments 中的应用程序是否存在内存泄漏,发现 Live Bytes for *Overall Allocations*Low Memory Alerts 出现在 100 MB 附近之前一直在上升。不过没有泄漏。

删除负责保存文件的行 ([[response body] writeToURL:url atomically:YES];) 并没有改变任何东西,所以我猜问题出在 RestKit 的某个地方。

在研究时,我偶然发现了一个method of ASIHTTPRequest,它允许直接下载文件,并认为类似的方法可以解决问题,但不确定。

RestKit 中是否有我错过的直接下载的可能性?

有没有我应该知道的更好的使用 RestKit 下载文件的方法?

【问题讨论】:

【参考方案1】:

我遇到了同样的问题,不幸的是我认为除了修改本地 RestKit 副本之外没有其他方法。问题出在- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data,正好在[_body appendData:data];。如您所见,RestKit 将响应的主体保存在内存中,并在从服务器发送字节时附加字节。这就是您收到内存不足警告的原因。我的解决方案是向 RKRequest 添加一个属性并将数据直接写入文件系统,具体取决于请求是否为大文件请求:

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
if ([_request dontKeepBytesInMemory]) 
    if ([[_request delegate] respondsToSelector:@selector(request:didReceivedData:totalBytesExectedToReceive:)]) 
        [[_request delegate] request:_request didReceivedData:data totalBytesExectedToReceive:_httpURLResponse.expectedContentLength];
    
 else 
    [_body appendData:data];
    if ([[_request delegate] respondsToSelector:@selector(request:didReceivedData:totalBytesReceived:totalBytesExectedToReceive:)]) 
        [[_request delegate] request:_request didReceivedData:[data length] totalBytesReceived:[_body length] totalBytesExectedToReceive:_httpURLResponse.expectedContentLength];
    

我还需要在协议中添加额外的 RKRequest 委托方法,这样我就可以单独处理大响应。原始委托方法定义了totalBytesReceived,它就是[_body length],但是如果您直接将字节写入文件系统,您只需检查当前文件大小即可跟踪下载状态。如果您正在寻找一种将字节直接保存到文件系统的好方法,请查看 NSFileHandle 类 - 它支持文件偏移量,因此您可以将任何 NSData 扔给它,它会自动为您附加它。

【讨论】:

您好,谢谢您的回答。我还没有时间研究这个,但这似乎是合法的。如果有问题,希望很快会回来并提供反馈...... 你能分享你的代码吗?我对使用 restkit 下载大文件很感兴趣... 很遗憾,我现在无法访问代码(更换了雇主),但如果你告诉我你到底卡在哪里,我很乐意指导你。

以上是关于使用 RestKit 下载和保存大文件的主要内容,如果未能解决你的问题,请参考以下文章

核心数据和大文件下载

aiohttp 异步http请求-5.下载大文件边下载边保存(节省内存)

NSURLSessionDownloadTask实现大文件下载

使用多部分请求将大文件上传到服务器并使用休息套件读取进度

RestKit 是不是支持带宽限制?

使用 RestKit 将大对象作为 JSON 发布