概要
iOSアプリからS3にデータをアップロードする部分を実装します。
また、認証部分はCognitoを使い、S3バケットの作成はAWS Amplifyを使って行います。
前提条件
AWS AmplifyによるiOSアプリ開発入門(Part1)が完了していること
Part1で作成したXcodeプロジェクトをそのまま使用します
AWS Amplifyを使ってS3バケットを作成
# Xcodeのルートプロジェクトに移動
$ cd ~/Downloads/amplify-learn
# S3バケットを作成
$ amplify add storage
# サービスを聞かれるので、「Content」を選択
# ラベル名を聞かれるので、任意のラベル名を入力(今回はデフォルトの設定のまま)
# S3のバケット名を聞かれるので、任意の名前を入力(今回はデフォルトの設定のまま)
# 誰がアクセス出来るかを聞かれるので、「Auth users only」を選択
# 認証ユーザーの権限を聞かれるので、「read/write」を選択
# S3バケットを作成するようにクラウド側に命令
$ amplify push
# 続けていいか聞かれるので、trueを選択
上記コマンドを実行すると、S3バケットが作成されます
また、IDプールで設定されている認証されたロールに、作成したバケットへのアクセス権限が
付与されていることが確認できると思います
→つまり、Cognitoで認証されたユーザは今回作成したS3バケットにアクセスできる権限が自動的に付与されれるということ
S3アップロード機能の実装
まずは、必要となるSDKのインストールを行います
Podfileを以下のように編集してください
target 'amplify-learn' do
use_frameworks!
# Pods for amplify-learn
pod 'AWSMobileClient', '~> 2.7.0'
pod 'AWSAuthUI', '~> 2.7.0'
pod 'AWSUserPoolsSignIn', '~> 2.7.0'
pod 'AWSS3', '~> 2.7.0' # S3用のSDKを追加
end
# Xcodeのルートプロジェクトに移動
$ cd ~/Downloads/amplify-learn
# 必要なSDKを追加
$ pod install --repo-update
次に、ボタンをクリックするとデータをアップロードする機能を追加します
amplify-learn.xcworkspaceを開きます
Main.storyboardに「S3アップロードボタン」を追加し、ViewController.swiftに対してアクション接続を追加してください
connectionはAction、NameをuploadDataToS3として設定します
ViewController.swiftを以下のように修正してください
transferUtility.uploadData関数の引数であるバケット名は適宜変更してください
import UIKit
import AWSMobileClient
// 以下を追加
import AWSS3
class ViewController: UIViewController {
@IBAction func pushLogoutButton(_ sender: Any) {
// サインアウト処理
AWSMobileClient.sharedInstance().signOut()
// サインイン画面を表示
AWSMobileClient.sharedInstance().showSignIn(navigationController: self.navigationController!, { (userState, error) in
if(error == nil){ //Successful signin
DispatchQueue.main.async {
print("Logged In")
}
}
})
}
// 以下の関数内の処理を追加
@IBAction func uploadDataToS3(_ sender: Any) {
let expression = AWSS3TransferUtilityUploadExpression()
expression.progressBlock = {(task, progress) in
DispatchQueue.main.async(execute: {
// Do something e.g. Update a progress bar.
})
}
var completionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock?
completionHandler = { (task, error) -> Void in
DispatchQueue.main.async(execute: {
// Do something e.g. Alert a user for transfer completion.
// On failed uploads, `error` contains the error object.
})
}
let data: Data = ("hello world").data(using: .utf8)! // Data to be uploaded
let transferUtility = AWSS3TransferUtility.default()
let format:DateFormatter = DateFormatter()
format.dateFormat = "yyyyMMdd-hhmmss"
let dateString:String = format.string(from: Date())
transferUtility.uploadData(data,
bucket: "YOUR_BUCKET_NAME",
key: "uploads/"+dateString+".txt",
contentType: "text/plain",
expression: expression,
completionHandler: completionHandler).continueWith {
(task) -> AnyObject? in
if let error = task.error {
print("Error: \(error.localizedDescription)")
}
if let _ = task.result {
// Do something with uploadTask.
}
return nil;
}
}
override func viewDidLoad() {
super.viewDidLoad()
AWSMobileClient.sharedInstance().initialize { (userState, error) in
if let userState = userState {
switch(userState){
case .signedIn:
DispatchQueue.main.async {
print("Logged In")
}
case .signedOut:
AWSMobileClient.sharedInstance().showSignIn(navigationController: self.navigationController!, { (userState, error) in
if(error == nil){ //Successful signin
DispatchQueue.main.async {
print("Logged In")
}
}
})
default:
AWSMobileClient.sharedInstance().signOut()
}
} else if let error = error {
print(error.localizedDescription)
}
}
}
}
上記コードの詳細な説明は行いませんが、重要な関数は以下です。
この部分で、認証周りのデフォルトの設定を取得してくれますので、
認証周りを意識せずにS3アップロードを行うことが可能です。
すでにサインイン済みであればデータをS3にアップロードできますし、サインアウト状態では、アップロードできません。
let transferUtility = AWSS3TransferUtility.default()
最終的な画面は以下の図のようになるかと思います
S3アップロードボタンをクリックすると、S3にデータが送信され保存されていることが確認できると思います。
※もし、サインイン画面が表示された場合は、Part1で作成したユーザでサインインを行ってください
まとめ
AWS Amplifyを使用したS3バケットの作成方法について説明しました。
もちろん、AWS CLIからもバケットを作成することは出来ますが、AWS Amplifyを用いると、
プロジェクトごとにバックエンドをまとめることが可能になりますので便利です。
つまり、amplify delete
とすると、CognitoもS3バケットもまとめて削除できます。
また、iOS SDKを使用して、データをS3に保存する部分も説明しました。
AWSMobileClientを使えば、バックエンドの処理をすべて任せることが出来るので、
S3アップロードの実装で認証周りを気にする必要はありません。
次はApp Syncとの連携について書く予定ですが、少し時間がかかるかもですorz