Restkit RKObjectManager在下载大量文件时请求超时



首先:我是RestKit的新手,所以这可能是一个很容易解决的问题。

我正在尝试下载很多文件。目前,我使用RKObjectManagergetObjectsAtPath:parameters:success:failure:方法来获取对象并将其映射到restkit。

然而,它似乎过早地开始了一些下载,然后当它们在队列中时超时。

我使用的代码:

- (void)removeResponseAndRequestDescriptors
{
    RKObjectManager *objectManager = [RKObjectManager sharedManager];
    [objectManager.requestDescriptors enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        [objectManager removeRequestDescriptor:obj];
    }];
    [objectManager.responseDescriptors enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        [objectManager removeResponseDescriptor:obj];
    }];
}

- (void)downloadAudioFileForAudio:(IBAudio *)audio
                           inBook:(IBBook *)book
                  downloadStatus:(void (^)(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead))downloadStatus
                         success:(void (^)(void))success
                         failure:(void (^)(NSError *error))failure
{
    RKObjectManager *objectManager = [RKObjectManager sharedManager];
    NSString *sessionID = (book.parent ? book.parent.user.session.sessionID : book.user.session.sessionID);
    [objectManager.HTTPClient setDefaultHeader:@"Accept" value:@"application/octet-stream"];
    [objectManager.HTTPClient setDefaultHeader:@"Session-Id" value:sessionID];
    [objectManager.HTTPClient getPath:[IBProperties downloadAudioEndPointWithIsbn:book.isbn andAnchor:audio.anchor] parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSString *folderPath = [self folderPathForBook:book];
        NSString *audioPath = [folderPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.mp3", audio.anchor]];
        NSData *audioData = [NSData dataWithData:responseObject];
        NSError *fileSystemSaveError;
        [self saveFile:audioData toFilePath:audioPath error:&fileSystemSaveError];
        if (fileSystemSaveError) {
            failure(fileSystemSaveError);
            return;
        }
        // Saving the context asap in case the app dies before it can autosave.
        NSError *coreDataSaveerror;
        [[[[RKObjectManager sharedManager] managedObjectStore] mainQueueManagedObjectContext] save:&coreDataSaveerror];
        if (coreDataSaveerror) {
            failure(coreDataSaveerror);
            return;
        }
        [audio setFilePath:audioPath];
        success();
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        failure(error);
    }];
    [objectManager.HTTPClient.operationQueue.operations.lastObject setDownloadProgressBlock:downloadStatus];
}

- (void)downloadAudioFiles
{
    for (IBAudio *audio in self.book.bookData.audios) {
        self.numberOfDownloads++;
        [self.downloadPercentagesFiles addObject:[[IBDownloadStatusOfAFile alloc] init]];
        NSInteger arrayIndex = [self.downloadPercentagesFiles count] - 1;
        [[IBDataBackendFetcher sharedBackendFetcher] downloadAudioFileForAudio:audio inBook:self.book downloadStatus:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
            IBDownloadStatusOfAFile *statusOfFile = [self.downloadPercentagesFiles objectAtIndex:arrayIndex];
            statusOfFile.bytesRead = bytesRead;
            statusOfFile.totalBytesRead = totalBytesRead;
            statusOfFile.totalBytesExpectedToRead = totalBytesExpectedToRead;
            [self updateDownloadProgress];
        } success:^{
            [self downloadDidComplete];
        } failure:^(NSError *error) {
            [self.dataProviderDelegate downloadDidFailWithError:error forBookDownloader:self];
        }];
    }
}

它似乎同时启动了所有下载,但实际的下载并没有启动。所以最后一次下载会超时。

有没有更好的方法来解决这个问题?

所有下载都将同时运行,因为您正在一行中进行所有getPath:调用(它们是异步调用)。由于每次下载都需要一段时间才能完成,这会导致以后调用的超时。

如果您希望每次下载都只在上一次完成后进行,我会创建一个名为getNextAudioFile:的方法和迭代器类属性。然后,在getPath:successfailure块中,递增迭代器并调用getNextAudioFile:

示例代码:

- (void)downloadAudioFiles
{
   // No for loop
   self.iterator = 0;
   // your call to DownloadAudioFileForAudio: ... for the first audio goes here
}
- (void)downloadAudioFileForAudio:(IBAudio *)audio
                           inBook:(IBBook *)book
                  downloadStatus:(void (^)(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead))downloadStatus
                         success:(void (^)(void))success
                         failure:(void (^)(NSError *error))failure
{
  // your code ...
  [objectManager.HTTPClient getPath:[IBProperties downloadAudioEndPointWithIsbn:book.isbn andAnchor:audio.anchor] parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject){
    // your code...
    // increment and get the next file
    self.iterator++;
    [self getNextAudioFile];
  } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    failure(error);
    // increment and get the next file
    self.iterator++;
    [self getNextAudioFile];
  }];
}
- (void)getNextAudioFile
{
  if(self.iterator < [self.book.bookData.audios count]){
    // make your downloadAudioFileForAudio: call for the next audio
  }
}

至少是这个主意!希望它能有所帮助。

将队列上的最大并发操作数设置为一些合理的值,如5。

[objectManager.HTTPClient.operationQueue setMaxConcurrentOperationCount:5];

(在开始任何请求之前)

最新更新