如何在后台会话中上传图像文件 (iOS)?

How to upload an image file in a background session (iOS)?

我无法在后台会话中从我设备的照片上传图像。当我调用 [session uploadTaskWithRequest:req fromFile:nsurl] 时,系统立即通过发送

进行投诉
Failed to issue sandbox extension for file file:///var/mobile/Media/DCIM/103APPLE/IMG_3984.JPG, errno = 1

到控制台。 (类似的 Stack Overflow 问题是 here

但是,如果我使用 [NSURLSessionConfiguration defaultSessionConfiguration](而不是我需要的 [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:id] 创建我的 NSURLSessionConfiguration) 如果我构造一个 NSData 对象从 NSURL 中上传,而不是直接从文件上传(后台会话需要),然后上传成功。顺便说一句,我正在将文件上传到我们的 Rackspace Cloud 帐户,并且能够通过简单的 Postman PUT 成功完成此操作。

问题出现在我的 uploadObject 方法中,看起来像:

-(void) uploadObject:(NSURL*)urlToBeUploadedIn
{
  NSDictionary *headers = @{ @"x-auth-token": state.tokenID,
                           @"content-type": @"image/jpeg",
                           @"cache-control": @"no-cache" };

  // create destination url for Rackspace cloud upload
  NSString *sURL = [NSString stringWithFormat:@"%@/testing_folder/%@.jpg", state.publicURL, [state generateImageName]]; 
  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:sURL]
                                                       cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                   timeoutInterval:10.0];
  [request setHTTPMethod:@"PUT"];
  [request setAllHTTPHeaderFields:headers];

  self.sessionIdentifier = [NSString stringWithFormat:@"my-background-session"];    
  //    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];  // when I use this instead of the line below the sandbox error goes away
  NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:self.sessionIdentifier];
  self.session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];

  NSURLSessionUploadTask *uploadTask = [self.session uploadTaskWithRequest:request fromFile:urlToBeUploadedIn];

  [uploadTask resume];
}

我调用 uploadObject: 的调用看起来像:

    PHFetchResult *fetchResult = [PHAsset fetchAssetsWithLocalIdentifiers:state.arrImagesToBeUploaded options:nil];

    PHAsset *phAsset = [fetchResult objectAtIndex:0]; // yes the 0th item in array is guaranteed to exist, above.
    [phAsset requestContentEditingInputWithOptions:nil
                                   completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info) {

                                       NSURL *imageURL = contentEditingInput.fullSizeImageURL;                           
                                       [self uploadObject:imageURL]; 

                                   }];

顺便说一句,我首先验证了我发送给 uploadObject: 的 NSURL,并调用了 fileExistsAtPath:,所以我知道我对该文件的引用是正确的。最后,我的代表打电话给

(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)dataIn

(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error does get invoked, although the data

确实会被服务器调用(尽管响应不会解析)所以,我从服务器返回的东西从未正确接收到图像。

解决方法是先将要上传的图片复制到应用的沙箱中。我用过:

NSError *err;
BOOL bVal = [myNSDataOb writeToURL:myDestinationURL options:0 error:&err];

并复制到我的应用程序的 'Documents' 目录中,但也可以使用:

NSError *err;
BOOL bVal = [[NSFileManager defaultManager] copyItemAtURL:myImageURL toURL:myDestinationURL error:&err];