I have an app which is currently uploading images to amazon S3. I have been trying to switch it from using NSURLConnection to NSURLSession so that the uploads can continue w
I made it work based on Zeev Vax answer. I want to provide some insight on problems I ran into and offer minor improvements.
Build a normal PutRequest, for instance
S3PutObjectRequest* putRequest = [[S3PutObjectRequest alloc] initWithKey:keyName inBucket:bucketName];
putRequest.credentials = credentials;
putRequest.filename = theFilePath;
Now we need to do some work the S3Client usually does for us
// set the endpoint, so it is not null
putRequest.endpoint = s3Client.endpoint;
// if you are using session based authentication, otherwise leave it out
putRequest.securityToken = messageTokenDTO.securityToken;
// sign the request (also computes md5 checksums etc.)
NSMutableURLRequest *request = [s3Client signS3Request:putRequest];
Now copy all of that to a new request. Amazon use their own NSUrlRequest class which would cause an exception
NSMutableURLRequest* request2 = [[NSMutableURLRequest alloc]initWithURL:request.URL];
[request2 setHTTPMethod:request.HTTPMethod];
[request2 setAllHTTPHeaderFields:[request allHTTPHeaderFields]];
Now we can start the actual transfer
NSURLSession* backgroundSession = [self backgroundSession];
_uploadTask = [backgroundSession uploadTaskWithRequest:request2 fromFile:[NSURL fileURLWithPath:theFilePath]];
[_uploadTask resume];
This is the code that creates the background session:
- (NSURLSession *)backgroundSession {
static NSURLSession *session = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.example.my.unique.id"];
session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
});
return session;
}
It took me a while to figure out that the session / task delegate needs to handle an auth challenge (we are in fact authentication to s3). So just implement
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler {
NSLog(@"session did receive challenge");
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
}