使用NSURLSession在后台上传文件时无法维持恒定速度

时间:2014-08-14 15:20:29

标签: ios amazon-s3 afnetworking nsurlsession nsurlsessionuploadtask

我正在尝试使用AFURLSessionManager在背景中将大约100张图像上传到S3,小批量10个像这里所做的那样 - Manage the number of active tasks in a background NSURLSession

我正在使用共享的NSURLSession,并在完成某些任务时根据更多任务添加任务。每个文件的平均大小约为1.6 MB,每个任务队列保证运行的任务数为5

以下是添加任务的方法: (也可以更容易阅读gist

    - (void) addTasksToSessionWithTaskObject:(Task*)taskObject withSessionInitialisationNeeded:(BOOL) needed{

        NSString *filePath = [[NSBundle mainBundle] pathForResource:pathForResourceFile ofType:resourceFileType];
        S3PutObjectRequest *putObjectRequest = [[S3PutObjectRequest alloc] initWithKey:targetFileKey
                                                                              inBucket:_bucketname];
        putObjectRequest.cannedACL = [S3CannedACL publicReadWrite];
        putObjectRequest.filename = filePath;
        putObjectRequest.contentType = [resourceFileType isEqualToString:@"MOV"] ? @"movie/mov" : @"image/jpg";
        putObjectRequest.endpoint = @"http://s3.amazonaws.com";
        putObjectRequest.contentLength=[[[NSFileManager defaultManager]
                                         attributesOfItemAtPath:filePath error:nil] fileSize];
        putObjectRequest.delegate = self;
        [putObjectRequest configureURLRequest];
        NSMutableURLRequest *request = [s3Client signS3Request:putObjectRequest];
        NSMutableURLRequest *request2 = [[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://s3.amazonaws.com/UploadTest/%@",taskObject.fileKey]]];

        [request2 setHTTPMethod:request.HTTPMethod];
        [request2 setAllHTTPHeaderFields:[request allHTTPHeaderFields]];

        if(needed) {

                sharedSession = [self backgroundSession];   
        }
   NSURLSessionUploadTask *task = [sharedSession uploadTaskWithRequest:request2           fromFile:forFileUrl];

    task.taskDescription = pathForResourceFile;
    [currentlyActiveTaskIdArray addObject:@([task taskIdentifier])];

    [task resume];
}

这就是我对代表所做的事情

- (void)URLSession:(NSURLSession *)sessionI task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error{

    dispatch_async(dispatch_get_main_queue(), ^{

        __block UIBackgroundTaskIdentifier bgTaskI = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
            [[UIApplication sharedApplication] endBackgroundTask:bgTaskI];
        }];

        if([currentlyActiveTaskIdArray containsObject:@([task taskIdentifier])]){
            [currentlyActiveTaskIdArray removeObject:@([task taskIdentifier])];
        }
        if(currentlyActiveTaskIdArray.count < LOWER_SLAB_FOR_TASKS + 1){   
            [self initiateS3UploadForSetOfTasksIsItBeginningOfUpload:NO];
        }
        [[UIApplication sharedApplication] endBackgroundTask:bgTaskI];
    }); 
}

以下是添加更多任务的代码

 - (void) initiateS3UploadForSetOfTasksIsItBeginningOfUpload:(BOOL)beginning{
        int i=0;
        for(Task *eachTaskObject in tasksArray){
            if(i < numberOfTasksTobeAdded){  
                [self addTasksToSessionWithTaskObject:eachTaskObject WithSessionInitialisationNeeded:NO];
                i++;
            }
        }
    }

我一直在前台模式和后台模式下运行100个文件的测试。在Foreground模式下,它以一致,稳定和恒定的速度上传文件,它在前3分钟内完成90个文件,在20秒内完成剩余的10个文件。

当我在后台模式下运行应用程序时,我希望它能够像在3分钟的前景窗口中一样快地上传前90个文件,然后在那之后放慢速度......但事实并非如此。在后台模式下,它在第一分钟上传了15个文件,然后开始减速...很多。它开始以较慢和较慢的间隔分8个文件批量上传:1分钟,3分钟,5分钟,10分钟,现在17分钟。我们在46分钟内获得65个文件。

有没有办法让它至少在第3分钟保持快速,或者在后台保持一致的速度?

更新:在Clay的评论之后,我已经从AFURLSessionManager切换回NSURLSession,因为他指出使用基于块的回调是NSURLSession的极其危险的业务。此外,我已经使用了HTTPMaximumConnectionsPerHost并将其设置为10左右 - 这已经给出了更好的结果,但远不及我想要的那样。

1 个答案:

答案 0 :(得分:2)

据我所知,setTaskDidCompleteBlock:不是Apple API,NSURLSession - 相关方法。 AFURLSessionManager方法(docs)。如果您在此使用AFNetworking,则需要宣布粗体,顶部,正面和中间。这与使用NSURLSession完全相同 。我猜想AFNetworking的基于NSURLSession的后台实现有自己的缺点和特性。

就我而言,无论我在上传NSURLSession次上传时取得的成功,都只使用了股票API。


解决问题等

  • 关于AFNetworking:我们将它用于一般的web api I / O.在NSURLSession问世的时候,AFNetworking确实没有强大的支持app-in-back操作,所以我没有使用它。也许是因为我经历了背景NSURLSession痛苦&amp;在“现在你有两个问题”的标题下,我对AFNetworking的背景感到怀疑。但也许他们现在已经破解了坚果。

    • 我努力争取一个NSURLSession。我开始对创作和骑士感到骄傲破坏会议,但发现这是一些真正的粗糙问题。经验似乎有所不同。

    • 我使用默认的HTTPMaximumConnectionsPerHost,没有问题。 Apple文档对默认值保持沉默,但这是lldb在我选择的随机特定设备/操作系统中告诉我的内容:
      (lldb) p [config HTTPMaximumConnectionsPerHost] (NSInteger) $0 = 4
      如果你在后台运行速度变慢的情况下遇到麻烦,我怀疑调整是否在正确的轨道上。

    • FWIW,后台NSURLSession不支持块接口,仅限委托。