使用 AWS SDK 將影象或視訊上傳到 S3

在開始使用示例之前,我建議建立一個帶有委託類成員的 Singleton,這樣你就可以實現在後臺上傳檔案的用例,讓使用者在上傳檔案時繼續使用你的應用程式,即使應用程式也是如此是背景。

讓我們開始吧,首先,我們應該建立一個代表 S3 配置的列舉:

enum S3Configuration : String
{
    case IDENTITY_POOL_ID   = "YourIdentityPoolId"
    case BUCKET_NAME        = "YourBucketName"
    case CALLBACK_KEY       = "YourCustomStringForCallBackWhenUploadingInTheBackground"
    case CONTENT_TYPE_IMAGE = "image/png"
    case CONTENT_TYPE_VIDEO = "video/mp4"
}

現在,我們應該在你的應用首次啟動時設定憑據,因此,我們應該在 AppDelegatedidFinishLaunchingWithOptions 方法中設定它們(注意你應該在 regionType param 設定你的區域):

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
{
  let credentialProvider = AWSCognitoCredentialsProvider(regionType: .EUWest1, identityPoolId: S3Configuration.IDENTITY_POOL_ID.rawValue)
  let configuration = AWSServiceConfiguration(region: .EUWest1, credentialsProvider: credentialProvider)
  AWSS3TransferUtility.registerS3TransferUtilityWithConfiguration(configuration, forKey: S3Configuration.CALLBACK_KEY.rawValue)
}

由於我們已經在 AppDelegate 中,因此我們應該實現 AWS SDK 處理的後臺回撥:

func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: () -> Void)
{
    //  Will print the identifer you have set at the enum: .CALLBACK_KEY
    print("Identifier: " + identifier)
    //  Stores the completion handler.
    AWSS3TransferUtility.interceptApplication(application,
                                              handleEventsForBackgroundURLSession: identifier,
                                              completionHandler: completionHandler)
}

現在,當使用者將應用程式移至後臺時,你的上傳將繼續實際上傳。

為了使用 AWS SDK 上傳檔案,我們必須將檔案寫入裝置併為 SDK 提供實際路徑。為了舉例,假設我們有一個 UIImage(也可能是一個視訊..),我們將它寫入臨時資料夾:

// Some image....
let image = UIImage()
let fileURL = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent(fileName)
let filePath = fileURL.path!
let imageData = UIImageJPEGRepresentation(image, 1.0)
imageData!.writeToFile(filePath, atomically: true)

FileURL 和 fileName 將在稍後用於實際上傳。

我們將需要定義兩個由 AWS SDK 提供的閉包,

  1. AWSS3TransferUtilityUploadCompletionHandlerBlock - 一個關閉,通知上次完成(或不完成)
  2. AWSS3TransferUtilityUploadProgressBlock - 一個閉包,通知傳送的每個位元組

如果你打算使用 Singleton,則應將這些型別定義為類成員。實現應如下所示:

var completionHandler : AWSS3TransferUtilityUploadCompletionHandlerBlock? =
    { (task, error) -> Void in

        if ((error) != nil)
        {
          print("Upload failed")
        }
        else
        {
          print("File uploaded successfully")
        }
    }

var progressBlock : AWSS3TransferUtilityUploadProgressBlock? = 
    { [unowned self] (task, bytesSent:Int64, totalBytesSent:Int64,  totalBytesExpectedToSend:Int64) -> Void in

     let progressInPercentage = Float(Double(totalBytesSent) / Double(totalBytesExpectedToSend)) * 100
     print(progressInPercentage)
    }

注意: 如果你使用的是 Singleton,則可能需要定義一個委託,該委託將報告進度或檔案完成時。如果你不使用 Singleton,則可以建立具有相關型別的靜態方法:

    static func uploadImageToS3(fileURL : NSURL,
                               fileName : String,
                progressFunctionUpdater : Float -> Void,
                            resultBlock : (NSError?) -> Void)
{
 //    Actual implementation .....
 //    ...
 //    ...
}
  1. progressFunctionUpdater - 將向具有進展的功能報告。
  2. resultBlock - 如果你返回 nil 然後上傳成功,你傳送錯誤物件

女士們,先生們,實際上傳:

        let fileData = NSData(contentsOfFile: fileURL.relativePath!)

        let expression = AWSS3TransferUtilityUploadExpression()
        expression.uploadProgress = progressBlock
        
        let transferUtility = AWSS3TransferUtility.S3TransferUtilityForKey(S3Configuration.CALLBACK_KEY.rawValue)
        
        transferUtility?.uploadData(fileData!,
            bucket: S3Configuration.BUCKET_NAME.rawValue,
            key: fileName,
            contentType: S3Configuration.CONTENT_TYPE_IMAGE.rawData,
            expression: expression,
            completionHander: completionHandler).continueWithBlock
            { (task : AWSTask) -> AnyObject? in
                
                if let error = task.error
                {
                    print(error)
                }
                if let exception = task.exception
                {
                    print("Exception: " + exception.description)
                }
                if let uploadTask = task.result as? AWSS3TransferUtilityUploadTask
                {
                    print("Upload started...")
                }
                
                return nil
        }

快樂 S3 上傳:)