Google Cloud Storage(GCS)は、非構造化データを低コストで管理できる優れたサービスです。アプリケーションからGCS APIを使って連携したり、GCSのURLを直接共有してファイルをアップロード/ダウンロードしたりできます。さらに、再開可能アップロードによってデータを複数のパートに分割してアップロードすることも可能です。

Google Cloud Storageへの失敗しないアップロード
再開可能アップロードが通常のアップロードより優れているのは、ネットワークの状態に強い点です。通信が可能なときにデータの一部をアップロードし、突然切断された場合は一時停止できます。これにより、大容量ファイルを最初からアップロードし直す必要がなくなり、帯域コストの削減にもつながります。
たとえば、モバイルアプリから写真や書類をWi-Fi経由のみでサーバーへアップロードしたい場合、モバイル回線に切り替わったタイミングで自動的に一時停止し、Wi-Fiに戻ったら再開する、といった挙動を実装できます。
GCSバケットでは、API呼び出し用のエンドポイントURLが次のように提供されています。

ソフトウェアでは、実装の詳細や使用しているツールをエンドユーザーから隠すのが基本です。これはアプリケーション内のGCSバケットにも当てはまり、GCSバケットを公開する際はカスタムURLを利用することをお勧めします。
https://mydrive.<your-company-domain-name>.com のようなカスタムURLでGCSバケットにアクセスするために、GoogleはGCPロードバランサー経由で構成可能な「Backend Bucket」サービスを提供しています。具体的な手順は以下のとおりです。
Backend BucketをGCSバケットに接続する手順
- GCPコンソールにログインし、左側のナビゲーションから Network Services -> Load Balancing を選択します。

2. 「Create Load Balancer」をクリックします。

3. 「HTTP(S) Load Balancing」を選び、「Start Configuration」をクリックします。

4. インターネット上のクライアントからバケットを利用するため、「From Internet to my VMs」を選択します。

5. ロードバランサーに名前を付け、Backend configuration で Backend buckets を選択します。

6. バックエンドバケットに名前を付け、このバックエンドサービスから利用するCloud Storageバケットを選択します。本記事の例では、API呼び出し時の認可トークン取得・受け渡しの煩雑さを避けるため、GCSバケットを公開状態にしています。

7. バックエンドバケットが正常に作成されると、バックエンドバケットの一覧が表示されます。

8. Frontend configuration では、サービスがGCSバケットと通信するための静的IPアドレスをロードバランサーに紐付けます。

9. 構成内容を確認し、設定を確定します。

10. 以下のように、Backend bucketサービスが正常に作成されているはずです。

Backend bucketサービスとロードバランサーが静的IPアドレスで接続されたら、カスタムIPアドレス(IPアドレスにドメイン名を割り当てている場合はURL)からGCS APIを実行できる状態になります。
バケット内のオブジェクト一覧を取得する
以下のcurlコマンドを実行します。

返ってくるレスポンスボディは次のとおりです。

単一オブジェクトをバケットにアップロードする
「map.png」を「worldmap_001.png」という名前でGCSバケットにアップロードするcurlコマンドです。

オブジェクト一覧を取得し、GCSバケット内に「worldmap_001.png」が存在することを確認します。
再開可能URLでファイルを複数パートに分けてアップロードする
サイズ312806バイトの「map.png」を、256KBの倍数となるように2つのパートに分割します。Google Cloud Storageの再開可能URL APIでは、最終パートを除く各パートが256KBの倍数である必要があります。

- POSTMAN などのREST APIクライアントから「uploadType=resumable」APIを呼び出し、ロケーションURLを取得します。

2. レスポンスから、各パートのアップロード先となるロケーションURLを取得します。

3. POSTMAN を使って1つ目のパート「xaa」をバケットにアップロードします。「Content-Range」ヘッダーの値が0から(「Content-Length」-1)になっていることを確認してください。

4. アップロード呼び出しに対して、HTTPステータスコード「308 Resume Incomplete」が返されます。

5. 2つ目のパート(最終パート)「xab」をバケットにアップロードします。

6. 最終パートのアップロード後、HTTPステータスコード「200 OK」が返ります。

7. アップロードされた画像(map.png)がバケットに保存されているか確認します。
