AFNetworking не может загружать большие файлы

В настоящее время я пытаюсь загрузить некоторые файлы с помощью AFNetworking, для относительно небольших файлов это, кажется, работает, но я пытаюсь загрузить файл немного большего размера (17 МБ), и он просто падает без каких-либо ошибок.

URL-адрес ссылается на локальный файл: http://test.local/wp-content/uploads/2012/07/test.pdf (я запускаю его в симуляторе, так что это доступно)

Единственный вывод, который я получаю, находится в блоке выполнения

прогресс: 0.009022

Когда я проверяю файловую систему, оказывается, что файл есть, но всего несколько килобайт.

Это известная ошибка с AFNetworking, или может я просто что-то не так делаю.

- (void)downloadIssue:(Issue *)issue
{
    NSString *fileName = [issue.pdf lastPathComponent];

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *filePath = [documentsDirectory stringByAppendingPathComponent:fileName];

    NSURL *url = [NSURL URLWithString:issue.pdf];
    AFHTTPClient *httpClient = [[[AFHTTPClient alloc] initWithBaseURL:url] autorelease];
    NSURLRequest *request = [httpClient requestWithMethod:@"GET" path:issue.pdf parameters:nil];

    AFURLConnectionOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:filePath append:NO];

    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(@"PDF DOWNLOAD COMPLETE");

        issue.pdf_location = filePath;

        // send out a notification with the issue
        [[NSNotificationCenter defaultCenter] postNotificationName:@"PDF_DOWNLOAD_COMPLETE" object:nil userInfo:[NSDictionary dictionaryWithObject:issue forKey:@"issue"]];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"PDF DOWNLOAD FAILED");

    // send out a notification with the issue
    [[NSNotificationCenter defaultCenter] postNotificationName:@"PDF_DOWNLOAD_FAILED" object:nil userInfo:[NSDictionary dictionaryWithObject:issue forKey:@"issue"]];
    }];

    [operation setDownloadProgressBlock:^(NSInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
        float progress = (float)totalBytesRead / totalBytesExpectedToRead;

        NSLog(@"progress: %f", progress);

        [[NSNotificationCenter defaultCenter] postNotificationName:@"PDF_DOWNLOAD_PROGRESS" object:nil userInfo:[NSDictionary dictionaryWithObjectsAndKeys: issue, @"issue", progress, @"progress", nil]];
    }];

    [_queue addOperation:operation];
}

person woutr_be    schedule 17.08.2012    source источник
comment
какие аварии? это EXC_BAD_ACCESS? вы пытались включить объект зомби.   -  person bitmapdata.com    schedule 17.08.2012
comment
Ну, это может быть проблема с памятью, вы можете попробовать AFURLConnectionOperation с набором исходящих свойств на файловый поток. Кроме того, создание экземпляра AFHTTPClient и использование его только для создания NSURLRequest для вас — это слишком много. AFHTTPClient подразумевается как клиент API REST, один экземпляр используется всеми вызовами.   -  person rckoenes    schedule 17.08.2012
comment
@bitmapdata.com, это не дает много информации, только Тема 1: сигнал SIGTRAP, у меня включены объекты-зомби.   -  person woutr_be    schedule 17.08.2012
comment
Раньше у меня был такой же опыт, как и у вас. попробуйте еще раз удалить postNotification в setDownloadPrgoressBlock. и повторил попытку :). все еще не работает?   -  person bitmapdata.com    schedule 17.08.2012
comment
@rckoenes, я только что пытался использовать только один экземпляр AFHTTPClient, но он имеет тот же эффект, маленькие файлы можно загружать, большие просто вылетают   -  person woutr_be    schedule 17.08.2012
comment
@woutr_be мое предложение о AFHTTPClient не имело никакого отношения к сбою. Просто то, как вы его используете, слишком убийственно. AFHTTPClient имеет такие методы, как: –getPath:parameters:success:failure:, – postPath:parameters:success:failure:, –putPath:parameters:success:failure: и –deletePath:parameters:success:failure:, которые избавляют от необходимости создавать собственную операцию и помещать ее в очередь. Все сделано AFHTTPClient   -  person rckoenes    schedule 17.08.2012
comment
@bitmapdata.com вау, это действительно помогло, теперь, кажется, не возникает никаких проблем ... Это потому, что рассылается слишком много уведомлений? Как вы сейчас отслеживаете прогресс в других классах?   -  person woutr_be    schedule 17.08.2012
comment
@bitmapdata.com Или, может быть, просто отправлять уведомление каждые 5%?   -  person woutr_be    schedule 17.08.2012
comment
@rckoenes Понятно, я знал, что использовал его неправильно, поэтому решил все равно изменить его.   -  person woutr_be    schedule 17.08.2012


Ответы (1)


Раньше у меня был такой же опыт, как и у вас. Попытка решить этот вопрос заняла почти две недели.

Такая же проблема была и у вас. Так что я рад, наконец, встретиться с вами :)

Вот решение.

если в блоке downloadProgress напрямую обновить пользовательский интерфейс, иногда возникает неизвестная ошибка. потому что неоднозначно, но я думаю, что основной поток рухнет. поэтому, downloadProgress блокирует только переменную обновления, выполняет пользовательский интерфейс обновления таймера, используя переменную.

//At the same time download
myTimer = [NSTimer timerWithTimeInterval:0.1f target:self selector:@selector(updateProgress:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:processTimer forMode:NSRunLoopCommonModes];

[operation setDownloadProgressBlock:^(NSInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead)
{
    //global ivar
    _progress = (float)totalBytesRead / totalBytesExpectedToRead;
}];

- (void)updateProgress:(NSTimer *)timer
{
    myProgressView.progress = _progress;
    if(fabs(1.f-_progress)<0.01f)
    {
        [timer invalidate];
    }
}
person bitmapdata.com    schedule 17.08.2012
comment
Я вижу, у меня тоже была такая мысль, просто создать таймер и обновлять его вручную, другая идея заключалась в том, чтобы просто обновлять его каждые 5%. Но спасибо большое, не думал, что сам бы до этого додумался - person woutr_be; 17.08.2012