使用backgroundSessionConfiguration和NSURLSessionUploadTask上传会导致应用崩溃

时间:2014-02-13 22:54:24

标签: ios iphone objective-c ios7 nsurlsession

我正在尝试使用NSURLSessionUploadTask进行新的花哨iOS 7后台上传,当我使用defaultSessionConfiguration运行它似乎工作,但是一旦我尝试backgroundSessionConfiguration它就会在我调用uploadTaskWithRequest的行崩溃:

以下是代码示例。奇怪的是,虽然网上有无数的downloadTaskWithRequest示例,但我找不到一个将背景和上传结合在一起的单一内容。

//Create a session w/ background settings
NSURLSessionConfiguration *config = [NSURLSessionConfiguration backgroundSessionConfiguration:@"identifierString.foo"];
NSURLSession *upLoadSession = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];

//Create a file to upload
UIImage *image = [UIImage imageNamed:@"onboarding-4@2x.png"];
NSData *imageData = UIImagePNGRepresentation(image);
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *URLs = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
NSString *documentsDirectory = [[URLs objectAtIndex:0] absoluteString];
NSString *filePath = [documentsDirectory stringByAppendingString:@"testfile.png"];
[imageData writeToFile:filePath atomically:YES];

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"https://file.upload/destination"]];
[request setHTTPMethod:@"PUT"];
NSURLSessionUploadTask *uploadTask = [upLoadSession uploadTaskWithRequest:request fromFile:[NSURL URLWithString:filePath] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    //code
}];

[uploadTask resume];

此代码在uploadTaskWithRequest的行中崩溃:...就在它到达最后的恢复行之前。

奇怪的是,当我使用除backgroundSessionConfiguration之外的任何配置类型时,这似乎工作正常。需要帮助!

提前致谢。

2 个答案:

答案 0 :(得分:15)

好的,所以这只是我在这里愚蠢而不彻底:

1)我设置了一个异常断点来获取阻止我看到实际异常错误打印输出的堆栈跟踪 - 哎呀。

2)不能使用具有backgroundSessionConfiguration完成回调的uploadTaskWithRequest版本(这并不奇怪,但仍未有详细记录)。

3)将您的PNG数据写入/ var / ...并使用file:/// var / ...将其提供给uploadTaskWithRequest(这只是尴尬,因为您通常不需要在两者之间进行转换单个命令序列)

很高兴在这里提供一个NSUrlSessionUploadTask示例代码,因为整个interwebs上似乎只有零个。 LMK,如果有人想要的话。

答案 1 :(得分:7)

根据要求,后台上传示例。请务必根据需要实施NSURLSessionDelegate和NSURLSessionTaskDelegate。

NSMutableArray *unsentPhotos = (NSMutableArray*)[sendingMessage objectForKey:@"unsentPhotos"];
TMessage *message = (TMessage*)[sendingMessage objectForKey:@"message"];
message.sendStatus = MS_PENDING_IMAGE_UPLOAD;

for (int i = 0; i < [unsentPhotos count]; i++) {
    NSString *fileName = [unsentPhotos objectAtIndex:i];
    NSLog(@"Initiating file upload for image %@", fileName);

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *srcImagePath = [NSString stringWithFormat:@"%@/messageCache/%@", [paths objectAtIndex:0], fileName];
    NSString *dataSrcImagePath = [srcImagePath stringByAppendingString:@".tmp"];

    //Encode file to data
    NSData *imageData = [NSData dataWithContentsOfFile:srcImagePath];
    if (!([imageData writeToFile:dataSrcImagePath atomically:YES])) {
        NSLog(@"Failed to save file.");
    }

    //Prepare upload request
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"https://blah.com"]];
    [request setHTTPMethod:@"PUT"];
    [request setValue:globalAPIToken forHTTPHeaderField:@"access_token"];
    [request setValue:[AppDelegate getMyUserID] forHTTPHeaderField:@"userid"];
    [request setValue:[NSString stringWithFormat:@"%d", message.teamID] forHTTPHeaderField:@"teamId"];
    [request setValue:[NSString stringWithFormat:@"%d", message.emailID] forHTTPHeaderField:@"messageId"];
    [request setValue:fileName forHTTPHeaderField:@"fileName"];
    [request setValue:@"1" forHTTPHeaderField:@"basefile"];

    if (i == 0) {
        //If this is the first upload in this batch, set up a new session

        //Each background session needs a unique ID, so get a random number
        NSInteger randomNumber = arc4random() % 1000000;
        NSURLSessionConfiguration *config = [NSURLSessionConfiguration backgroundSessionConfiguration: [NSString stringWithFormat:@"testSession.foo.%d", randomNumber]];
        config.HTTPMaximumConnectionsPerHost = 1;
        session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
        //Set the session ID in the sending message structure so we can retrieve it from the
        //delegate methods later
        [sendingMessage setValue:session.configuration.identifier forKey:@"sessionId"];
    }
    uploadTask = [session uploadTaskWithRequest:request fromFile:[NSURL URLWithString:[NSString stringWithFormat:@"file://%@", dataSrcImagePath]]];
    [uploadTask resume];
}