NSURLSession and amazon S3 uploads

后端 未结 7 1843
傲寒
傲寒 2020-12-12 21:27

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

7条回答
  •  时光取名叫无心
    2020-12-12 22:02

    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);
    }
    

提交回复
热议问题