2011-12-04 41 views

Trả lời

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

Bạn thậm chí có thể thêm một khối tiến bộ: khối // Cài đặt Tải lên để trở sự tiến bộ của tập tin tải lên [hoạt động setDownloadProgressBlock:^(NSInteger bytesWritten, lâu dài totalBytesWritten, totalBytesExpectedToRead lâu dài) {float progress = totalBytesWritten/(float) totalBytesExpectedToRead; NSLog (@ "Tỷ lệ phần trăm tải xuống:% f %%", tiến độ * 100); }]; – Climbatize

+19

Hãy cẩn thận rằng mã trên sẽ tải xuống bất kỳ phản hồi nào từ máy chủ đến luồng đầu ra, vì vậy nếu máy chủ phản hồi với mã trạng thái 404, trang 404 sẽ được lưu vào đường dẫn được chỉ định. Bạn phải kiểm tra khối thành công cho operation.response.statusCode. – leolobato

+0

Tính năng này hoạt động với tôi trên iOS6. Cảm ơn @mattt –

31

Tôi sẽ bật ra khỏi câu trả lời @ mattt và gửi một phiên bản dành cho AFNetworking 2.0 sử dụng 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

Tôi chắc chắn sẽ khuyên bạn nên làm theo cách này với thư viện AFNetworking mới hơn – Thomas

+2

@swilliams [AFHTTPRequestOperationManager manager] sẽ tạo đối tượng người quản lý mới bằng cách sử dụng AFJSONResponseSerializer mặc định, bạn có muốn không? Tôi nghĩ tốt hơn là nên tạo AFNoneResponseSerialize để cho tệp bị ảnh hưởng – onmyway133

+0

làm cách nào tôi có thể lấy thông số tiến trình tải xuống trong trường hợp này? – shshnk

5

Tôi đang nói về AFNetworking 2,0

[AFHTTPRequestOperationManager manager] tạo đối tượng quản lý với mặc định AFJSONResponseSerializer, và nó thực hiện các loại hạn chế nội dung. Hãy xem điều này

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

Vì vậy, chúng tôi cần tạo bộ nối tiếp không đáp ứng và sử dụng AFHTTPRequestOperationManager như bình thường.

Đây là 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 

Cách sử dụng

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

để chúng tôi có thể nhận được toàn bộ file mà không cần bất kỳ serialization

1

Vâng, nó là tốt hơn để sử dụng AFNetworking 2.0 cách với AFHTTPRequestOperationManager. Theo cách cũ, tệp của tôi đã tải xuống nhưng vì một số lý do không cập nhật trong hệ thống tệp.

Gắn thêm câu trả lời của swilliam, để hiển thị tiến trình tải xuống, trong AFNetworking 2.0 bạn làm tương tự - chỉ cần đặt khối tiến trình tải xuống sau khi đặt luồng đầu ra.

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

Đây là phương pháp của tôi để tạo ra byte chuỗi:

- (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

khi tôi tải video và bấm vào trở lại hoàn thành tải xuống với. và một lần nữa tôi bấm vào video thời gian tôi nhận được lỗi này => MediaPlayerErrorDomain Code = -11800 ... vì vậy plz giúp tôi –

0

Ngoài các câu trả lời trước, với AFNetworking 2.5.0 và iOS7/8 Tôi đã tìm thấy rằng thêm bước mở luồng đầu ra cũng cần thiết để ngăn ứng dụng treo (và cuối cùng bị rơi do thiếu bộ nhớ).

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: @ "application/octet-stream"]; có thể khác nhau tùy thuộc vào những gì bạn mong đợi

4

Documentation page có ví dụ với phần 'Tạo Tải Task':

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! Mã hoạt động với iOS 7+ (được thử nghiệm với AFNetworking 2.5.1)

+0

khi tôi tải video và bấm vào trở lại hoàn thành tải xuống với. và một lần nữa tôi bấm vào video thời gian tôi nhận được lỗi này => MediaPlayerErrorDomain Code = -11800 ... vì vậy plz giúp tôi –

4

Từ AFNetworking tài liệu. Lưu tệp đã tải vào tài liệu của bạn. 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]; 
Các vấn đề liên quan