AFNetworking 仅在请求成功时下载和保存数据

Posted

技术标签:

【中文标题】AFNetworking 仅在请求成功时下载和保存数据【英文标题】:AFNetworking Download & save data when request is successful only 【发布时间】:2016-02-04 13:10:44 【问题描述】:

在我的 ios 应用程序中,我使用 AFNetworking 库来管理所需的 HTTP 操作。

我已经创建了一个下载文件的方法:

+ (void)downloadFile:(File *)file progress:(void (^)(NSUInteger receivedBytes, long long totalReceivedBytes, long long totalExpectedBytes))progress success:(void (^)())success failure:(void (^)(NSError *error))failure

    NSURLRequest *request = [NSURLRequest requestWithURL:file.url];

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];

    operation.outputStream = [NSOutputStream outputStreamToFileAtPath:[FCFileManager pathForTemporaryDirectoryWithPath:file.key.lastPathComponent] append:NO];

    [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead)
    
        progress(bytesRead, totalBytesExpectedToRead, totalBytesExpectedToRead);
    ];

    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
    
        success();
    

    failure:^(AFHTTPRequestOperation *operation, NSError *error)
    
        failure(error);
    ];

    [operation start];

虽然,这种方法有问题。如果正在取消下载(强制退出),该文件仍然可以在应用程序目录中找到。如何创建文件下载,仅在下载成功后将文件保存到documents目录?

【问题讨论】:

也许在 completionBlock 中你可以捕捉到 operation.error。如果为 nil,则下载完成。 【参考方案1】:

我建议下载将文件保存在临时文件位置,然后在完成块中将生成的临时文件复制到“实时”位置。当应用启动时,临时位置的任何数据都可以被认为是不完整的并被删除

【讨论】:

这听起来像是一种解决方法...也许有更好的方法来处理下载操作? 您唯一的其他选择是不将文件在下载时写入磁盘,但将其保存在内存中。这确实意味着在下载大文件时,您将耗尽所有设备的内存。 @flaxicode 的建议被广泛使用并被普遍接受为一个很好的解决方案。【参考方案2】:

使用 Foundation 框架本身的NSUrlSession 将自行处理失败的下载:

- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData
                                   completionHandler:(void (^)(NSURL *location,
                                                               NSURLResponse *response,
                                                               NSError *error))completionHandler

你应该只在创建任务时传递一个 nil 完成处理程序 其代表包括 URLSession:downloadTask:didFinishDownloadingToURL: 方法。

您的应用可以通过两种方式获取 resumeData 对象:

如果您的应用通过调用取消现有传输 cancelByProducingResumeData:,会话对象传递一个resumeData 您在该调用中提供的完成处理程序的对象。

如果传输失败,会话对象提供一个 NSError 对象 给它的委托或任务的完成处理程序。在那里面 对象,userInfo 中的 NSURLSessionDownloadTaskResumeData 键 字典包含一个 resumeData 对象。

创建任务后,您必须通过调用它的简历来启动它 方法。

如果请求成功完成,则 完成处理程序块包含临时文件的位置, 并且错误参数为零。如果请求失败,位置 参数为 nil 并且错误参数包含有关 失败。

如果你想为此使用 AFNetworking,它应该是完全兼容的,因为它有 AFURLSessionManager 来处理 NSUrlSession

【讨论】:

你说的是按照例子下载:github.com/AFNetworking/AFNetworking? 我说的是一般的文件下载,正如我所说,Apple 已经在他们的框架中处理了您需要的内容,而无需创建临时文件。文档很清楚。

以上是关于AFNetworking 仅在请求成功时下载和保存数据的主要内容,如果未能解决你的问题,请参考以下文章

AFNetworking 2.0,使用 CoreData (MagicalRecord) 保存下载状态

AFNetworking 文件下载错误 Error Domain=NSCocoaErrorDomain Code=260

AFNetworking,完成请求时回调?

使用 AFnetworking 保存 mp4

发出太多 AFNetworking 请求时超时

iOS开发-AFNetworking封装Get(自定义HTTP Header)和Post请求及文件下载