2011-12-04 38 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]; 
相關問題