Как загрузить файл и сохранить его в каталоге документов с помощью Afnetworking?

StackOverflow https://stackoverflow.com/questions/8372661

  •  27-10-2019
  •  | 
  •  

Вопрос

Я использую библиотеку 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 и опубликовать версию для 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];

я говорю о Afnetworking 2.0

[AFHTTPRequestOperationManager manager] Создает объект 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);
        }
    }];

чтобы мы могли получить весь файл без сериализации

Страница документации Имеет пример в разделе «Создание задачи загрузки»:

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

Черт! Кодовая работа с iOS 7+ (протестировано с помощью Afnetworking 2.5.1)

Из 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];
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.ResponseRializer.acceptableContentTypes = [nsset setWithObject: @"Application/Octet-Stream"]; может варьироваться в зависимости от того, что вы ожидаете

Да, лучше использовать AFNetworking 2.0 способ с AFHTTPRequestOperationManager. Анкет С Old Way мой файл сделал загрузку, но по какой -то причине не обновил в файловой системе.

Добавление к Свиллиам Ответ, чтобы показать прогресс скачать, в 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;
}

В дополнение к предыдущим ответам, с Afnetworking 2.5.0 и IOS7/8 я обнаружил, что дополнительный шаг от открытия выходного потока также необходим для предотвращения висящего приложения (и, в конечном итоге, сбоя из -за отсутствия памяти).

operation.outputStream = [NSOutputStream outputStreamToFileAtPath:dest
                                                          append:NO];
[operation.outputStream open];
[operation start];
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top