Amazon S3 Pre-Signed URLs: For Background Transfer

If you are working with large file transfers, you may want to perform uploads and downloads in the background. To do this, you need to create a background session using NSURLSession and then transfer your objects using pre-signed URLs.

The following sections describe pre-signed S3 URLs. To learn more about NSURLSession, see Using NSURLSession.

Pre-Signed URLs#

By default, all Amazon S3 resources are private. If you want your users to have access to Amazon S3 buckets or objects, you can assign appropriate permissions with an IAM policy.

Alternatively, you can use pre-signed URLs to give your users access to Amazon S3 objects. A pre-signed URL provides access to an object without requiring AWS security credentials or permissions.

When you create a pre-signed URL, you must provide your security credentials, specify a bucket name, an object key, an HTTP method, and an expiration date and time. The pre-signed URL is valid only for the specified duration.

Build a Pre-Signed URL#

The following example shows how to build a pre-signed URL for an Amazon S3 download in the background.

Swift
AWSS3PreSignedURLBuilder.default().getPreSignedURL(getPreSignedURLRequest).continueWith { (task:AWSTask<NSURL>) -> Any? in
    if let error = task.error as? NSError {
        print("Error: \(error)")
        return nil
    }

    let presignedURL = task.result
    print("Download presignedURL is: \(presignedURL)")

    let request = URLRequest(url: presignedURL as! URL)
    let downloadTask: URLSessionDownloadTask = URLSession.shared.downloadTask(with: request)
    downloadTask.resume()

    return nil
}
Objective-C
AWSS3GetPreSignedURLRequest *getPreSignedURLRequest = [AWSS3GetPreSignedURLRequest new];
getPreSignedURLRequest.bucket = @"myBucket";
getPreSignedURLRequest.key = @"myImage.jpg";
getPreSignedURLRequest.HTTPMethod = AWSHTTPMethodGET;
getPreSignedURLRequest.expires = [NSDate dateWithTimeIntervalSinceNow:3600];

[[[AWSS3PreSignedURLBuilder defaultS3PreSignedURLBuilder] getPreSignedURL:getPreSignedURLRequest]
    continueWithBlock:^id(AWSTask *task) {

    if (task.error) {
        NSLog(@"Error: %@",task.error);
    } else {

        NSURL *presignedURL = task.result;
        NSLog(@"download presignedURL is: \n%@", presignedURL);

        NSURLRequest *request = [NSURLRequest requestWithURL:presignedURL];
        self.downloadTask = [self.session downloadTaskWithRequest:request];
        //downloadTask is an instance of NSURLSessionDownloadTask.
        //session is an instance of NSURLSession.
        [self.downloadTask resume];

    }
    return nil;
}];

The [receding example uses GET as the HTTP method: AWSHTTPMethodGET. For an upload request to Amazon S3, we would need to use a PUT method and also specify a content type.

Swift
getPreSignedURLRequest.httpMethod = .PUT
let fileContentTypeStr = "text/plain"
getPreSignedURLRequest.contentType = fileContentTypeStr
Objective-C
getPreSignedURLRequest.HTTPMethod = AWSHTTPMethodPUT;
NSString *fileContentTypeStr = @"text/plain";
getPreSignedURLRequest.contentType = fileContentTypeStr;

Here's an example of building a pre-signed URL for a background upload to S3.

Swift
let getPreSignedURLRequest = AWSS3GetPreSignedURLRequest()
getPreSignedURLRequest.bucket = "myBucket"
getPreSignedURLRequest.key = "myFile.txt"
getPreSignedURLRequest.httpMethod = .PUT
getPreSignedURLRequest.expires = Date(timeIntervalSinceNow: 3600)

//Important: set contentType for a PUT request.
let fileContentTypeStr = "text/plain"
getPreSignedURLRequest.contentType = fileContentTypeStr

AWSS3PreSignedURLBuilder.default().getPreSignedURL(getPreSignedURLRequest).continueWith { (task:AWSTask<NSURL>) -> Any? in
    if let error = task.error as? NSError {
        print("Error: \(error)")
        return nil
    }

    let presignedURL = task.result
    print("Download presignedURL is: \(presignedURL)")

    var request = URLRequest(url: presignedURL as! URL)
    request.cachePolicy = .reloadIgnoringLocalCacheData
    request.httpMethod = "PUT"
    request.setValue(fileContentTypeStr, forHTTPHeaderField: "Content-Type")

    let uploadTask: URLSessionTask = URLSession.shared.uploadTask(with: request, fromFile: URL(fileURLWithPath: "your/file/path/myFile.txt"))
    uploadTask.resume()

    return nil
}
Objective-C
AWSS3GetPreSignedURLRequest *getPreSignedURLRequest = [AWSS3GetPreSignedURLRequest new];
getPreSignedURLRequest.bucket = @"myBucket";
getPreSignedURLRequest.key = @"myFile";
getPreSignedURLRequest.HTTPMethod = AWSHTTPMethodPUT;
getPreSignedURLRequest.expires = [NSDate dateWithTimeIntervalSinceNow:3600];

//Important: set contentType for a PUT request.
NSString *fileContentTypeStr = @"text/plain";
getPreSignedURLRequest.contentType = fileContentTypeStr;

[[[AWSS3PreSignedURLBuilder defaultS3PreSignedURLBuilder] getPreSignedURL:getPreSignedURLRequest]
                                                continueWithBlock:^id(AWSTask *task) {
    if (task.error) {
        NSLog(@"Error: %@",task.error);
    } else {
        NSURL *presignedURL = task.result;
        NSLog(@"upload presignedURL is: \n%@", presignedURL);

        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:presignedURL];
        request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
        [request setHTTPMethod:@"PUT"];
        [request setValue:fileContentTypeStr forHTTPHeaderField:@"Content-Type"];

        self.uploadTask = [self.session uploadTaskWithRequest:request fromFile:self.uploadFileURL];
        //uploadTask is an instance of NSURLSessionDownloadTask.
        //session is an instance of NSURLSession.
        [self.uploadTask resume];
    }
    return nil;
}];