如何使用AFNetworking下载文件并将其保存到文档目录中?

我正在使用AFNetworking库。 我不知道如何下载文件并将其保存到文档目录。

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"..."]]; AFHTTPRequestOperation *operation = [[[AFHTTPRequestOperation alloc] initWithRequest:request] autorelease]; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"filename"]; operation.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:NO]; [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"Successfully downloaded file to %@", path); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"Error: %@", error); }]; [operation start]; 

我会反弹@ mattt的答案并发布使用AFHTTPRequestOperationManager AFNetworking 2.0的版本。

 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"filename"]; AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; AFHTTPRequestOperation *op = [manager GET:@"http://example.com/file/to/download" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"successful download to %@", path); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"Error: %@", error); }]; op.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:NO]; 

我正在谈论AFNetworking 2.0

[AFHTTPRequestOperationManager manager]使用默认的AFJSONResponseSerializer创buildpipe理器对象,并执行内容types限制。 看看这个

 - (BOOL)validateResponse:(NSHTTPURLResponse *)response data:(NSData *)data error:(NSError * __autoreleasing *)error 

所以我们需要创build一个没有响应的序列化器,并正常使用AFHTTPRequestOperationManager

这是AFNoneResponseSerializer

 @interface AFNoneResponseSerializer : AFHTTPResponseSerializer + (instancetype)serializer; @end @implementation AFNoneResponseSerializer #pragma mark - Initialization + (instancetype)serializer { return [[self alloc] init]; } - (instancetype)init { self = [super init]; return self; } #pragma mark - AFURLResponseSerializer - (id)responseObjectForResponse:(NSURLResponse *)response data:(NSData *)data error:(NSError *__autoreleasing *)error { return data; } @end 

用法

 self.manager = [AFHTTPRequestOperationManager manager]; self.manager.responseSerializer = [AFNoneResponseSerializer serializer]; [self.manager GET:@"https://sites.google.com/site/iphonesdktutorials/xml/Books.xml" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) { if (success) { success(responseObject); } } failure:^(AFHTTPRequestOperation *operation, NSError *error) { if (failure) { failure(error); } }]; 

这样我们就可以在没有任何序列化的情况下获得整个文件

文档页面有“创build下载任务”部分的示例:

 NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration]; NSURL *URL = [NSURL URLWithString:@"http://example.com/download.zip"]; NSURLRequest *request = [NSURLRequest requestWithURL:URL]; NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) { NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil]; return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]]; } completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) { NSLog(@"File downloaded to: %@", filePath); }]; [downloadTask resume]; 

NB! 使用iOS 7+的代码(使用AFNetworking 2.5.1进行testing)

 AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; manager.responseSerializer = [AFCompoundResponseSerializer serializer]; manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"application/octet-stream"]; AFHTTPRequestOperation *operation = [manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { if (responseObject) { // your code here } else { // your code here } } failure:^(AFHTTPRequestOperation *operation, NSError *error) { }]; [operation start]; 

// manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@“application / octet-stream”]; 可以根据你的期望而有所不同

从AFNetworking文档。 保存到加载的文件到您的文件。 AFNetworking 3.0

 NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration]; NSURL *URL = [NSURL URLWithString:@"http://example.com/download.zip"]; NSURLRequest *request = [NSURLRequest requestWithURL:URL]; NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) { NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil]; return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]]; } completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) { NSLog(@"File downloaded to: %@", filePath); }]; [downloadTask resume]; 

是的,最好使用AFNetworking 2.0方式与AFHTTPRequestOperationManager 。 用旧的方式我的文件没有下载,但由于某种原因没有在文件系统中更新。

附加到swilliam的答案,以显示下载进度,在类似的AFNetworking 2.0 – 设置输出stream后设置下载进度块。

 __weak SettingsTableViewController *weakSelf = self; operation.outputStream = [NSOutputStream outputStreamToFileAtPath:newFilePath append:NO]; [operation setDownloadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToRead) { float progress = totalBytesWritten / (float)totalBytesExpectedToRead; NSString *progressMessage = [NSString stringWithFormat:@"%@ \n %.2f %% \n %@ / %@", @"Downloading ...", progress * 100, [weakSelf fileSizeStringWithSize:totalBytesWritten], [weakSelf fileSizeStringWithSize:totalBytesExpectedToRead]]; [SVProgressHUD showProgress:progress status:progressMessage]; }]; 

这是我创buildstring的方法:

 - (NSString *)fileSizeStringWithSize:(long long)size { NSString *sizeString; CGFloat f; if (size < 1024) { sizeString = [NSString stringWithFormat:@"%d %@", (int)size, @"bytes"]; } else if ((size >= 1024)&&(size < (1024*1024))) { f = size / 1024.0f; sizeString = [NSString stringWithFormat:@"%.0f %@", f, @"Kb"]; } else if (size >= (1024*1024)) { f = size / (1024.0f*1024.0f); sizeString = [NSString stringWithFormat:@"%.0f %@", f, @"Mb"]; } return sizeString; } 

除了以前的答案,AFNetworking 2.5.0和iOS7 / 8,我发现打开输出stream的额外步骤也是需要的,以防止应用程序挂起(最终由于内存不足而崩溃)。

 operation.outputStream = [NSOutputStream outputStreamToFileAtPath:dest append:NO]; [operation.outputStream open]; [operation start];