2011-12-04 37 views

回答

138
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]; 
+10

您甚至可以添加一个进度块: //设置上传块返回文件的进度上传 [操作setDownloadProgressBlock:^(NSInteger的bytesWritten,长长totalBytesWritten,很长很长totalBytesExpectedToRead){ 浮动progress = totalBytesWritten /(float)totalBytesExpectedToRead; NSLog(@“Download Percentage:%f %%”,progress * 100); }]; – Climbatize

+19

请注意,上面的代码将下载从服务器到输出流的任何响应,因此如果服务器以状态码404响应,则404页面将保存到指定的路径。您必须检查operation.response.statusCode的成功块。 – leolobato

+0

这在iOS6上适用于我。谢谢@mattt –

31

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

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]; 
+1

我肯定会推荐用这种方法用更新的AFNetworking库 – Thomas

+2

@swilliams [AFHTTPRequestOperationManager manager]将使用默认的AFJSONResponseSerializer创建新的管理器对象,你想这么做吗?我认为最好创建AFNoneResponseSerialize以使文件不受影响 – onmyway133

+0

如何获取下载进度参数? – shshnk

5

我谈论AFNetworking 2.0

[AFHTTPRequestOperationManager manager]默认AFJSONResponseSerializer创建管理对象,它执行的内容类型的限制。看看这个

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

因此,我们需要创建一个无响应串并使用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); 
     } 
    }]; 

这样我们就可以得到整个文件,而无需任何系列化

1

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

追加到swilliam的回答,展现下载进度,在AFNetworking 2.0你做人之道 - 设置输出流后刚刚成立的下载进度块。

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

这是我的方法来创建字节字符串:

- (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; 
} 
+0

当我下载视频,并点击返回witho下载完成。并再次点击视频,当我得到这个错误=> MediaPlayerErrorDomain代码= -11800 ...所以plz帮助我 –

0

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

operation.outputStream = [NSOutputStream outputStreamToFileAtPath:dest 
                  append:NO]; 
[operation.outputStream open]; 
[operation start]; 
2
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:@ “应用程序/八位字节流”];可以根据你所期望的

4

Documentation page有部分“创建一个下载任务”而变化。例如:

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进行测试)

+0

当我下载视频,并点击返回witho下载完成。并再次点击视频,当我得到这个错误=> MediaPlayerErrorDomain代码= -11800 ...所以plz帮助我 –

4

AFNetworking docs。 将加载的文件保存到您的文档中。 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]; 
相关问题