LoginSignup
18
13

More than 3 years have passed since last update.

SwiftでAWS S3に画像をアップロードする時のTips

Last updated at Posted at 2019-12-10

はじめに

GameWith AdventCalendar 2019の11日目の記事になります。

AWSのモバイルSDKの使い方は定期的に更新されるイメージがあるため、最近の書き方が気になって検証してみました。
今回の記事では、S3の指定バケットに画像を直接アップロードする部分のコードや、気をつけるべきポイントなどを簡単に紹介します!

※ ライブラリの導入や、AWS側の設定などについては今回は省略しています。

必要なファイルとプロパティ

import AWSCore
import AWSS3

// 必須
var uploadCompletionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock?
// 以下はなくても良い
var uploadProgressBlock: AWSS3TransferUtilityProgressBlock?
var uploadProgress: Float = 0

AWSS3TransferUtilityUploadCompletionHandlerBlock は名前の通り、アップロードが完了したか否かを取得するために利用します。
AWSS3TransferUtilityProgressBlock はアップロードの進捗を取得するために利用します。
アップロードするデータが画像ファイルなど比較的容量の小さいものの場合は、数秒もかからずアップロードが完了するため必要ないかもしれませんが、uploadProgress と合わせて利用することで、ナビゲーションバーの下にプログレスバーを置いたり、進捗を示す専用のアラートを用意したりUXを高めることができます。

アップロード用のメソッドを定義

func uploadImage(data: Data) {

    // アップロードの進捗を取得(なくても良い)
    uploadProgressBlock = {(task, progress) in
        DispatchQueue.main.async {
            if self.uploadProgress < Float(progress.fractionCompleted) {
                self.uploadProgress = Float(progress.fractionCompleted)
            }
        }
    }

    // アップロードの完了可否を取得
    uploadCompletionHandler = { (task, error) -> Void in
        DispatchQueue.main.async {
            if let error = error {
               // エラー処理
            } else {
               // アップロードが完了しているのでその後させたい処理
            }
        }
    }

    // AWSのアップロード用の設定(今回はexamplebucket/photoに画像を上げる想定)
    let bucketName = "examplebucket"
    // 時刻を入れたりユーザーIDを入れたりファイル名が被らないようアプリによって定義しましょう
    let uploadKeyName = "photo/\(UUID().uuidString).png"
    let contentType = "image/png"

    let expression = AWSS3TransferUtilityUploadExpression()
    expression.progressBlock = uploadProgressBlock

    let transferUtility = AWSS3TransferUtility.default()
    transferUtility.uploadData(data, bucket: bucketName, key: uploadKeyName, contentType: contentType, expression: expression, completionHandler: uploadCompletionHandler).continueWith { (task) -> AnyObject? in
        if let error = task.error {
            // エラー処理
        }
        if let _ = task.result {
            // アップロードが開始したのでその後させたい処理(あれば)
        }
        return nil
    }
}

補足

今回は Data 型のオブジェクトをアップロードしていますが、UIImage からData への変換は下記の標準コードで簡単に実装できるので以下を使うケースが多いです。

public func pngData() -> Data? // return image as PNG. May return nil if image has no CGImageRef or invalid bitmap format

気をつけるべき箇所

アップロードが始まったが、特にプログレスも得られず、エラーも返ってこないといったケースの際はバケットポリシーの設定漏れのことが多いです。

下記の設定は一旦全ての操作を許可するものなので、本番の際はユーザーに該当バケットに対してどういった操作を許可するのかを考慮して設定しましょう。

{
  "Version":"2012-10-17",
  "Statement":[
    {
      "Effect":"Allow",
      "Principal": "*",
      "Action":[
          "s3:*"
      ],
      "Resource":["arn:aws:s3:::examplebucket/*"]
    }
  ]
}
18
13
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
13