NSURLSession and amazon S3 uploads

后端 未结 7 1839
傲寒
傲寒 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:03

    The answers here are slightly outdated, spent a great deal of my day trying to get this work in Swift and the new AWS SDK. So here's how to do it in Swift by using the new AWSS3PreSignedURLBuilder (available in version 2.0.7+):

    class S3BackgroundUpload : NSObject {
    
        // Swift doesn't support static properties yet, so have to use structs to achieve the same thing.
        struct Static {
            static var session : NSURLSession?
        }
    
        override init() {
            super.init()
    
            // Note: There are probably safer ways to store the AWS credentials.
            let configPath = NSBundle.mainBundle().pathForResource("appconfig", ofType: "plist")
            let config = NSDictionary(contentsOfFile: configPath!)
            let accessKey = config.objectForKey("awsAccessKeyId") as String?
            let secretKey = config.objectForKey("awsSecretAccessKey") as String?
            let credentialsProvider = AWSStaticCredentialsProvider .credentialsWithAccessKey(accessKey!, secretKey: secretKey!)
    
            // AWSRegionType.USEast1 is the default S3 endpoint (use it if you don't need specific endpoints such as s3-us-west-2.amazonaws.com)
            let configuration = AWSServiceConfiguration(region: AWSRegionType.USEast1, credentialsProvider: credentialsProvider)
    
            // This is setting the configuration for all AWS services, you can also pass in this configuration to the AWSS3PreSignedURLBuilder directly.
            AWSServiceManager.defaultServiceManager().setDefaultServiceConfiguration(configuration)
    
            if Static.session == nil {
                let configIdentifier = "com.example.s3-background-upload"
    
                var config : NSURLSessionConfiguration
                if NSURLSessionConfiguration.respondsToSelector("backgroundSessionConfigurationWithIdentifier:") {
                    // iOS8
                    config = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(configIdentifier)
                } else {
                    // iOS7
                    config = NSURLSessionConfiguration.backgroundSessionConfiguration(configIdentifier)
                }
    
                // NSURLSession background sessions *need* to have a delegate.
                Static.session = NSURLSession(configuration: config, delegate: self, delegateQueue: nil)
            }
        }
    
        func upload() {
            let s3path = "/some/path/some_file.jpg"
            let filePath = "/var/etc/etc/some_file.jpg"
    
            // Check if the file actually exists to prevent weird uncaught obj-c exceptions.
            if NSFileManager.defaultManager().fileExistsAtPath(filePath) == false {
                NSLog("file does not exist at %@", filePath)
                return
            }
    
            // NSURLSession needs the filepath in a "file://" NSURL format.
            let fileUrl = NSURL(string: "file://\(filePath)")
    
            let preSignedReq = AWSS3GetPreSignedURLRequest()
            preSignedReq.bucket = "bucket-name"
            preSignedReq.key = s3path
            preSignedReq.HTTPMethod = AWSHTTPMethod.PUT                   // required
            preSignedReq.contentType = "image/jpeg"                       // required
            preSignedReq.expires = NSDate(timeIntervalSinceNow: 60*60)    // required
    
            // The defaultS3PreSignedURLBuilder uses the global config, as specified in the init method.
            let urlBuilder = AWSS3PreSignedURLBuilder.defaultS3PreSignedURLBuilder()
    
            // The new AWS SDK uses BFTasks to chain requests together:
            urlBuilder.getPreSignedURL(preSignedReq).continueWithBlock { (task) -> AnyObject! in
    
                if task.error != nil {
                    NSLog("getPreSignedURL error: %@", task.error)
                    return nil
                }
    
                var preSignedUrl = task.result as NSURL
                NSLog("preSignedUrl: %@", preSignedUrl)
    
                var request = NSMutableURLRequest(URL: preSignedUrl)
                request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData
    
                // Make sure the content-type and http method are the same as in preSignedReq
                request.HTTPMethod = "PUT"
                request.setValue(preSignedReq.contentType, forHTTPHeaderField: "Content-Type")
    
                // NSURLSession background session does *not* support completionHandler, so don't set it.
                let uploadTask = Static.session?.uploadTaskWithRequest(request, fromFile: fileUrl)
    
                // Start the upload task:
                uploadTask?.resume()
    
                return nil
            }
        }
    }
    
    extension S3BackgroundUpload : NSURLSessionDelegate {
    
        func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
            NSLog("did receive data: %@", NSString(data: data, encoding: NSUTF8StringEncoding))
        }
    
        func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
            NSLog("session did complete")
            if error != nil {
                NSLog("error: %@", error!.localizedDescription)
            }
            // Finish up your post-upload tasks.
        }
    }
    
    0 讨论(0)
提交回复
热议问题