SwiftでAWS S3へデータをアップロード

AWS SDK for iOSを使ってアプリからAWS S3に動画をアップロードする処理をやってみた。 ローカルのデータをアップロードして、保存先のURLを取得します。

準備

  • プロジェクトにAWS SDKをインストール

pod 'AWSS3'

  • ユーザー認証の仕組みとかを実装できる Amazon CognitoというAWSサービスを登録する必要もあります。

  • S3の設定 Bucketを作成します。 permissionはとりあえず、EveryOne が UploadとRead できるようにしておきます。

これで準備完了。

実装

application:didFinishLaunchingWithOptionsでCognitoを使ってSDKのセットアップ

let credentialsProvider = AWSCognitoCredentialsProvider(regionType: RegionType, identityPoolId: IdentityPoolId)
let configuration = AWSServiceConfiguration(region: DefaultServiceRegionType, credentialsProvider: credentialsProvider)
AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = configuration

実際にアップロードするところは

internal func upload() -> NSURL {
        let uploadRequest = AWSS3TransferManagerUploadRequest()
        uploadRequest.body = origin
        uploadRequest.key = remote
        uploadRequest.bucket = BucketName
        let transferManager = AWSS3TransferManager.defaultS3TransferManager()
        transferManager.upload(uploadRequest).continueWithBlock { task -> AnyObject! in
            if task.result != nil {
                if let bucket = uploadRequest.bucket, key = uploadRequest.key {
                    let url = NSURL(string: "http://s3.amazonaws.com/\(bucket)/\(key)")
                    return url
                }
            }
        }
    }

originにアップロードするデータのfilepath、remoteにS3に保存するデータの名前を入れます。 アップロードが成功すると保存先のURLが返ってきます。

使いやすいように、SwiftTaskを使ってこんな感じのクラスを作ってみた

import AWSS3
import SwiftTask

class S3Uploader {

    typealias UploadTask = Task<Void, NSURL, NSError>

    private var origin: NSURL?
    private var remote: String?

    internal init(origin: NSURL, remote: String) {
        self.origin = origin
        self.remote = remote
    }

    internal func upload() -> UploadTask {
        return UploadTask { progress, fulfill, reject, configure in
            guard let origin = self.origin, remote = self.remote else { return }
            let uploadRequest = AWSS3TransferManagerUploadRequest()
            uploadRequest.body = origin
            uploadRequest.key = remote
            uploadRequest.bucket = AppConfig.AWSS3.BucketName
            let transferManager = AWSS3TransferManager.defaultS3TransferManager()
            transferManager.upload(uploadRequest).continueWithBlock { task -> AnyObject! in
                if let error = task.error {
                    reject(error)
                }
                if task.result != nil {
                    if let bucket = uploadRequest.bucket, key = uploadRequest.key {
                        if let url = NSURL(string: "http://s3.amazonaws.com/\(bucket)/\(key)") {
                            fulfill(url)
                        }
                    }
                }
                return nil
            }
        }
    }
}

けっこう頻繁に更新されている公式のサンプルもあって、参考になった。(日本人の方がつくってるっぽい)

github.com