Skip to content

Instantly share code, notes, and snippets.

@aishowdown
Last active September 23, 2018 23:03
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aishowdown/e88f6595e5a23d936e29 to your computer and use it in GitHub Desktop.
Save aishowdown/e88f6595e5a23d936e29 to your computer and use it in GitHub Desktop.
import AWSS3
class S3Uploader: NSObject, NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate {
var urlSession: NSURLSession?
var uploadTask: NSURLSessionUploadTask?
var url: String?
var filename: String?
var callback: ((Bool, String?) -> Void)? = nil;
//This needs to Deinit when unwind segue, but right now it only deinits sometimes !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
deinit {
println("Deinit S3Uploader")
}
override init() {
super.init()
//Init Connection to S3
struct Static {
static var session: NSURLSession?
static var token: dispatch_once_t = 0
}
//dispatch_once(&Static.token) { [unowned self] in
let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(CONSTANTS.BackgroundSessionUploadIdentifier)
Static.session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil)
//}
self.urlSession = Static.session
}
convenience init(url: NSURL, contentType: String) {
self.init()
self.uploadToS3(url, contentType: contentType)
}
convenience init(url: NSURL, contentType: String, onCompletion: ((success: Bool, url: String?) -> Void)?){
self.init();
callback = onCompletion;
self.uploadToS3(url, contentType: contentType)
}
func generateKey(contentType: String) -> String {
let timestamp = NSDate().timeIntervalSince1970
var ret = timestamp.description + CONSTANTS.UID;
//TODO: we could actually look at the file contents here to decide
switch(contentType.lowercaseString){
case "movie/mp4":
ret += ".mp4"
case "image/jpg", "image/jpeg":
ret += ".jpg"
case "image/png":
ret += ".png"
default:
ret += ".txt"
}
return ret;
}
func uploadToS3(url:NSURL, contentType: String?) -> String? {
if (self.uploadTask != nil){
return nil;
}
self.filename = self.generateKey(contentType!);
let getPreSignedURLRequest = AWSS3GetPreSignedURLRequest()
getPreSignedURLRequest.bucket = CONSTANTS.S3BucketName
getPreSignedURLRequest.key = filename
getPreSignedURLRequest.HTTPMethod = AWSHTTPMethod.PUT
getPreSignedURLRequest.expires = NSDate(timeIntervalSinceNow: 3600)
getPreSignedURLRequest.contentType = contentType
AWSS3PreSignedURLBuilder.defaultS3PreSignedURLBuilder().getPreSignedURL(getPreSignedURLRequest).continueWithBlock { [unowned self] (task:AWSTask!) -> (AnyObject!) in
if (task.error != nil) {
NSLog("Error: %@", task.error)
} else {
let presignedURL = task.result as! NSURL!
if (presignedURL != nil) {
//NSLog("upload presignedURL is: \n%@", presignedURL)
var request = NSMutableURLRequest(URL: presignedURL)
request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData
request.HTTPMethod = "PUT"
//contentType in the URLRequest must be the same as the one in getPresignedURLRequest
request .setValue(contentType, forHTTPHeaderField: "Content-Type")
self.uploadTask = self.urlSession?.uploadTaskWithRequest(request, fromFile: url)
self.uploadTask?.resume()
}
}
return nil;
}
self.url = "https://s3-us-west-1.amazonaws.com/fireworksprofiles/" + self.filename!;
println("setting new url to: "+self.url!)
return self.url;
}
//TODO: retry on fail
func URLSession(session: NSURLSession, task: NSURLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
let progress = Float(totalBytesSent) / Float(totalBytesExpectedToSend)
let notification = NSNotification(name: NotificationCenters.UploadPercentage,
object: ["type": "progress", "progress": progress.description])
NSNotificationCenter.defaultCenter().postNotification(notification)
//NSLog("UploadTask progress: %lf", progress)
/*
dispatch_async(dispatch_get_main_queue()) {
self.progressView.progress = progress
self.statusLabel.text = "Uploading..."
}*/
}
func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
if (error == nil) {
/*dispatch_async(dispatch_get_main_queue()) {
self.statusLabel.text = "Upload Successfully"
}*/
NSLog("S3 UploadTask Completed Successfully");
let notification = NSNotification(name: NotificationCenters.UploadPercentage,
object: ["type": "finished", "progress": "100", "success": "true", "url": self.url!])
NSNotificationCenter.defaultCenter().postNotification(notification)
} else {
/*dispatch_async(dispatch_get_main_queue()) {
self.statusLabel.text = "Upload Failed"
}*/
let notification = NSNotification(name: NotificationCenters.UploadPercentage,
object: ["type": "error", "progress": "100"])
NSNotificationCenter.defaultCenter().postNotification(notification)
NSLog("S3 UploadTask: %@ completed with error: %@", task, error!.localizedDescription);
}
if(callback != nil){
callback!(error == nil, self.url);
}
self.urlSession?.finishTasksAndInvalidate();
self.urlSession = nil
self.uploadTask = nil
}
func URLSessionDidFinishEventsForBackgroundURLSession(session: NSURLSession) {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
if ((appDelegate.backgroundUploadSessionCompletionHandler) != nil) {
let completionHandler:() = appDelegate.backgroundUploadSessionCompletionHandler!;
appDelegate.backgroundUploadSessionCompletionHandler = nil
completionHandler
}
NSLog("Completion Handler has been invoked, background upload task has finished.");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment