AFNetworking 2.0 отслеживает процесс загрузки файлов

Я относительно новичок в AFNetworking 2.0. Используя приведенный ниже фрагмент кода, я смог успешно загрузить фотографию на свой URL-адрес. Я хотел бы отслеживать процесс добавочной загрузки, но не могу найти пример этого в версии 2.0. Мое приложение — iOS 7, поэтому я выбрал AFHTTPSessionManager.

Может ли кто-нибудь предложить пример того, как изменить этот фрагмент, чтобы отслеживать ход загрузки?

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:@"myimage.jpg"], 1.0);

[manager POST:@"http://myurl.com" parameters:dataToPost constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
    [formData appendPartWithFileData:imageData name:@"attachment" fileName:@"myimage.jpg" mimeType:@"image/jpeg"];
} success:^(NSURLSessionDataTask *task, id responseObject) {
    NSLog(@"Success %@", responseObject);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
    NSLog(@"Failure %@, %@", error, [task.response description]);
}];

person Benchtop Creative    schedule 12.12.2013    source источник


Ответы (2)


Интерфейс AFHTTPSession не предоставляет метод для установки блока выполнения. Вместо этого вам нужно будет сделать следующее:

// 1. Create `AFHTTPRequestSerializer` which will create your request.
AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];

// 2. Create an `NSMutableURLRequest`.
NSMutableURLRequest *request =
    [serializer multipartFormRequestWithMethod:@"POST" URLString:@"http://www.myurl.com"
                                    parameters:dataToPost
                     constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
                       [formData appendPartWithFileData:imageData
                                                   name:@"attachment"
                                               fileName:@"myimage.jpg"
                                               mimeType:@"image/jpeg"];
                     }];

// 3. Create and use `AFHTTPRequestOperationManager` to create an `AFHTTPRequestOperation` from the `NSMutableURLRequest` that we just created.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
AFHTTPRequestOperation *operation =
    [manager HTTPRequestOperationWithRequest:request
                                     success:^(AFHTTPRequestOperation *operation, id responseObject) {
                                       NSLog(@"Success %@", responseObject);
                                     } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                       NSLog(@"Failure %@", error.description);
                                     }];

// 4. Set the progress block of the operation.
[operation setUploadProgressBlock:^(NSUInteger __unused bytesWritten,
                                    long long totalBytesWritten,
                                    long long totalBytesExpectedToWrite) {
  NSLog(@"Wrote %lld/%lld", totalBytesWritten, totalBytesExpectedToWrite);
}];

// 5. Begin!
[operation start];

Кроме того, вам не нужно считывать изображение через UIImage, а затем снова сжимать его с помощью JPEG, чтобы получить NSData. Просто используйте +[NSData dataWithContentsOfFile:], чтобы прочитать файл прямо из вашего пакета.

person StatusReport    schedule 12.12.2013
comment
Спасибо за отличный ответ. Однако блок setUploadProgressBlock не вызывается. Он просто вызывается только один раз после завершения загрузки. Можете ли вы помочь мне объяснить и исправить это? - person lenhhoxung; 13.06.2014
comment
Обратите внимание, что -multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock: теперь устарело, вместо него можно использовать -multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:error (есть дополнительный параметр ошибки)! - person gklka; 01.08.2014

Это правда, что интерфейс AFHTTPSessionManager не предоставляет метод для отслеживания хода загрузки. Но AFURLSessionManager есть.

Поскольку унаследованный класс AFURLSessionManager AFHTTPSessionManager может отслеживать ход загрузки следующим образом:

NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer]  multipartFormRequestWithMethod:@"POST" URLString:kUploadImageURL parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
    [formData appendPartWithFileData:UIImageJPEGRepresentation(image, 0.5) name:@"uploadFile" fileName:@"image" mimeType:@"image/jpeg"];
} error:nil];

NSProgress *progress;
NSURLSessionDataTask *uploadTask = [[AFHTTPSessionManager sharedManager] uploadTaskWithStreamedRequest:request progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
    if (!error) {
        //handle upload success
    } else {
        //handle upload failure
    }
}];
[uploadTask resume];
[progress addObserver:self forKeyPath:@"fractionCompleted" options:NSKeyValueObservingOptionNew context:NULL];

за пределами

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([keyPath isEqualToString:@"fractionCompleted"] && [object isKindOfClass:[NSProgress class]]) {
        NSProgress *progress = (NSProgress *)object;
        //progress.fractionCompleted tells you the percent in CGFloat
    }
}

Вот метод 2 (обновлено)

использовать KVO для отслеживания прогресса означает, что self должен быть жив во время наблюдения. Более элегантным способом является метод AFURLSessionManager setTaskDidSendBodyDataBlock, например:

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager setTaskDidSendBodyDataBlock:^(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend) {
    //during the progress
}];

NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer]  multipartFormRequestWithMethod:@"POST" URLString:kUploadImageURL parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
    [formData appendPartWithFileData:UIImageJPEGRepresentation(image, 0.5) name:@"uploadFile" fileName:@"image" mimeType:@"image/jpeg"];
} error:nil];

NSURLSessionDataTask *uploadTask = [manager uploadTaskWithStreamedRequest:request progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
    if (!error) {
        //handle upload success
    } else {
        //handle upload failure
    }
}];
[uploadTask resume];
person dopcn    schedule 03.12.2014
comment
setTaskDidSendBodyDataBlock вызывается, когда все данные отправлены. Это не очень постепенный прогресс. как получить пошаговый процент прогресса? Я использую dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler: - person Hassy; 01.12.2016
comment
Странно то, что когда он заканчивает загрузку, он вызывается несколько раз. Это может быть проблема, связанная с потоками - person Hassy; 01.12.2016
comment
Я пропустил NSURLSessionConfiguration с AFHTTPSessionManager. Его вызывали постепенно. Хотя в dataTaskWithRequest:uploadProgress:downloadProgress:complete‌​onHandler: uploadProgress все еще вызывается после завершения. - person Hassy; 01.12.2016
comment
Вроде тоже работает правильно. У меня был код в dispatch_async(dispatch_get_main_queue(), ^{}); блок, он вызывается в конце. - person Hassy; 01.12.2016