Firebase Storageに画像をアップロードをするサンプルを作ってみた！


## 追記

サンプルプロジェクトをBitBucketにあげているので良かったらみてください。
また、Firebase上からはすでにプロジェクトを削除しているので動作はしません。
自身のものと置き換えてから実験などどうぞ:bow: 
https://bitbucket.org/nnsnodnb/firebasestoragesample/src

## 環境

- OSX 10.11.6
- Xcode 8
- CocoaPods 0.39.0
- iOS 10.0.1 (iPhone5)

## 準備

1. Xcodeの新規プロジェクトを作成及びFirebaseコンソールでのアプリ登録
2. Firebaseのプロジェクト適用

上記は済ませている前提で

ちなみにPodfileは以下

```ruby:Podfile
use_frameworks!

target 'Sample' do
    pod 'Firebase'
    pod 'Firebase/Storage'
end
```

## Firebase Storageの設定

![スクリーンショット_2016-09-19_午前6_10_41.png](https://qiita-image-store.s3.amazonaws.com/0/97280/7021ffc7-a428-198e-072a-6f71266d0f0f.png "スクリーンショット_2016-09-19_午前6_10_41.png")

まずはルールから設定します。デフォルトの設定だと、認証をしているユーザしかファイルアップロードができない設定のようです。
今回は私なりに適当に設定したルールを置いておきます。

```:StorageRule
service firebase.storage {
  match /b/<YOUR-GS-URL>.appspot.com/o {
    match /{allPaths=**} {
      allow read:if request.auth != null;
      allow write;
    }
  }
}
```

また、ルール作成の手助けになったサイトは以下です。感謝！！
https://groups.google.com/forum/#!topic/firebase-talk/WCShGLoRO2I

意味合いとしては `read` には認証がいる。 `write` は誰でもできる！と言った感じ。
今回はアップロードのみなので `write` は認証なしでOKにしました。
また、以下のようにすると認証なしで誰でも読み書きが可能になります。

```:StorageRule
service firebase.storage {
  match /b/<YOUR-GS-URL>.appspot.com/o {
    match /{allPaths=**} {
      allow read, write
    }
  }
}
```

## 実装

![IMG_4460.PNG](https://qiita-image-store.s3.amazonaws.com/0/97280/bf8cb80c-eb74-fef1-2358-9c584d79c536.png "IMG_4460.PNG")

画面自体はこんな感じのボタンがあるだけのものです。

今回は、カメラロールから画像を選択してそれをアップロードしてみます。
iOS10で実装を行ったため、 `Info.plist` にカメラロール使用許可を求めるものを設定しました。

`Privacy - Photo Library Usage Description` を追加してそれっぽいものを追加しておきましょう！

![IMG_4461.PNG](https://qiita-image-store.s3.amazonaws.com/0/97280/eeb87198-212d-4ef0-01fe-121caab06bab.png "IMG_4461.PNG")

実際にカメラロールにアクセスするときにこんな感じにアラートが表示されます！

実際に使ったソースコードは以下

```swift:ViewController.swift
import UIKit
import Firebase
import FirebaseStorage

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let ud = UserDefaults.standard
        ud.set(0, forKey: "count")
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    @IBAction func selectImageWithLibrary(_ sender: AnyObject) {
        pickImageFromLibrary()
    }
    
    func countPhoto() -> String {
        let ud = UserDefaults.standard
        let count = ud.object(forKey: "count") as! Int
        ud.set(count + 1, forKey: "count")
        return String(count)
    }
}


// MARK: UINavigationControllerDelegate
extension ViewController: UINavigationControllerDelegate {
    func pickImageFromLibrary() {
        if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.photoLibrary) {
            let controller = UIImagePickerController()
            controller.delegate = self
            controller.sourceType = UIImagePickerControllerSourceType.photoLibrary
            
            present(controller, animated: true, completion: nil)
        }
    }
}

// MARK: UIImagePickerControllerDelegate
extension ViewController: UIImagePickerControllerDelegate {
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo
        info: [String : Any]) {
        let storage = FIRStorage.storage()
        let storageRef = storage.reference(forURL: "gs://<YOUR-GS-APP>.appspot.com")
        
        if let data = UIImagePNGRepresentation(info[UIImagePickerControllerOriginalImage] as! UIImage) {
            let reference = storageRef.child("image/" + NSUUID().uuidString + "/" + countPhoto() + ".jpg")
            reference.put(data, metadata: nil, completion: { metaData, error in
                print(metaData)
                print(error)
            })
            dismiss(animated: true, completion: nil)
        }
    }
}
```

### 流れ

1. UserDefaultsに `0` を追加。(起動時に毎回呼ばれる...これは各自修正お願いします)
2. 「アップロードする」ボタンを押下する。
3. アクセス許諾アラートが表示される。(OKだった前提)
4. フォトライブラリ(カメラロール)から任意の画像を選ぶ。
5. UIImagePickerControllerDelegateによってFirebase Storageにアップロードする準備をする。
6. UserDefaultsからファイルアップロード回数を確認しそれとUUIDをフォルダ構成をしてアップロードをする。

完全なものにしたいのであれば `UserDefaults` ではなく `Keychain` を使ってカウントをしていくのがいいと思います。

## 結果

![スクリーンショット 2016-09-19 午前6.06.17.png](https://qiita-image-store.s3.amazonaws.com/0/97280/d3f0c95f-efbd-10fa-2d43-096e40c627f5.png "スクリーンショット 2016-09-19 午前6.06.17.png")

カレントディレクトリの下に `image/<UUID>/[0-9].jpg` の形で保存することができました！

## 最後に

Firebase Storageのアップロード容量がいくらか忘れてしまったのですが(誰か教えてください)、これを使えば簡単な共有アプリとか作れそうですね！