App Engine と Google Cloud Storage のサンプル

このチュートリアルでは、App Engine Go アプリから Cloud Storage にアクセスするために必要な操作について学習します。ここでは、非対話型のサンプルを使用して、Cloud Storage バケット内でファイルの作成、書き込み、読み取り、一覧表示を行う方法を説明します。

このサンプルを実行すると、Cloud Storage バケット上で処理が行われ、ブラウザに出力結果が表示されます。

目標

  • サンプルアプリを Google App Engine にデプロイして実行する。
  • 作成したファイルを Cloud Storage バケットに書き込む方法を学習する。
  • Cloud Storage バケットからファイルを読み取る方法を学習する。
  • Cloud Storage バケット内でファイルをコピーする方法を学習する。
  • Cloud Storage に存在するファイルの一覧を作成する方法を学習する。

料金

App Engine の使用は特定条件のもとで無料です。App Engine の合計使用量が、App Engine 無料割り当てに指定された制限未満である場合、このチュートリアルを実行しても料金は掛かりません。

始める前に

  1. GCP Console で GCP プロジェクトを作成または選択します。プロジェクトに App Engine アプリケーションが含まれていることを確認します。

    App Engine に移動

    プロジェクトに App Engine アプリケーションが存在する場合には、ダッシュボードが開きます。存在しない場合には、App Engine アプリケーションを配置するリージョンを選択するように指示されます。

  2. App Engine 用 SDK をダウンロードして、インストールします

  3. Cloud Storage を設定します。

    1. デフォルトの Cloud Storage バケットをアクティブ化します。

    2. Cloud Storage クライアント ライブラリをダウンロードして、インストールします。

サンプル プロジェクトをダウンロードする

プロジェクトをダウンロードするには、次のいずれかの方法を選択します。

  • サンプルコードを含むプロジェクトのクローンを作成します。

    go get -u -d github.com/GoogleCloudPlatform/golang-samples/docs/appengine/storage
    
  • .zip ファイルとしてサンプルをダウンロードした後、作業ディレクトリにサンプルを抽出します。

サンプルをデプロイして実行する

サンプルアプリを App Engine にデプロイし、ブラウザでサンプルを表示するには、次の操作を行います。

  1. サンプルコードが入っているディレクトリに移動します。

    cd $GOPATH/src/github.com/GoogleCloudPlatform/golang-samples/docs/appengine/storage
    
  2. アプリケーションのルート ディレクトリ(app.yaml ファイルがある場所。例: golang-samples/docs/appengine/storage)から次のコマンドを実行します。

    gcloud app deploy
    

    コマンドラインからアプリケーションをデプロイする方法については、Go App のデプロイをご覧ください。

  3. ブラウザを起動して http://[YOUR_PROJECT_ID].appspot.com でサンプルを表示するには、次のコマンドを実行します。

    gcloud app browse
    
  4. アプリの結果を確認します。ブラウザには、Cloud Storage バケットでスクリプトが実行したアクションの詳細が表示されます。

    このサンプル ファイルでは、ファイルの書き込み、読み取り、コピー、一覧表示だけでなく、オブジェクトの権限を表示したり、アクセス制御リスト(ACL)の操作を行ったりできます。また、Cloud Storage バケットからすべてのデモファイルを削除して、クリーンアップを行うことができます。

    結果の例:

    デモサンプル

コードのチュートリアル

サンプルコードには Cloud Storage の追加機能も含まれていますが、このチュートリアルでは、Cloud Storage バケットの読み取りと書き込み、バケットの内容の一覧表示のみを行います。

app.yaml について

通常、どのアプリでも app.yaml ファイルに設定が定義されています。他の App Engine アプリと同様に、アプリケーションの設定を細かく指定することができます。

application: your-app-id
version: v1
runtime: go
api_version: go1

handlers:
- url: /.*
  script: _go_app

このファイルで使用可能な構成オプションについては、app.yaml リファレンスをご覧ください。

app.go インポートについて

app.go ファイルには、次のインポートが含まれています。

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"strings"

	"cloud.google.com/go/storage"
	"golang.org/x/net/context"
	"google.golang.org/api/iterator"
	"google.golang.org/appengine"
	"google.golang.org/appengine/file"
	"google.golang.org/appengine/log"
)

App Engine と Cloud Storage に必要なファイルのインポートは次のとおりです。

  • google.golang.org/appengine
  • google.golang.org/appengine/file
  • cloud.google.com/go/storage

Cloud Storage バケットを指定する

Cloud Storage でオペレーションを行う前に、バケット名を指定する必要があります。最も簡単な方法は、プロジェクトのデフォルトのバケットを使用する方法です。このバケットは、App Engine コンテキストから取得できます。

// Use `dev_appserver.py --default_gcs_bucket_name GCS_BUCKET_NAME`
// when running locally.
bucket, err := file.DefaultBucketName(ctx)
if err != nil {
	log.Errorf(ctx, "failed to get default GCS bucket name: %v", err)
}

Cloud Storage へのファイルの書き込み

Cloud Storage にファイルを書き込むには:

// createFile creates a file in Google Cloud Storage.
func (d *demo) createFile(fileName string) {
	fmt.Fprintf(d.w, "Creating file /%v/%v\n", d.bucketName, fileName)

	wc := d.bucket.Object(fileName).NewWriter(d.ctx)
	wc.ContentType = "text/plain"
	wc.Metadata = map[string]string{
		"x-goog-meta-foo": "foo",
		"x-goog-meta-bar": "bar",
	}
	d.cleanUp = append(d.cleanUp, fileName)

	if _, err := wc.Write([]byte("abcde\n")); err != nil {
		d.errorf("createFile: unable to write data to bucket %q, file %q: %v", d.bucketName, fileName, err)
		return
	}
	if _, err := wc.Write([]byte(strings.Repeat("f", 1024*4) + "\n")); err != nil {
		d.errorf("createFile: unable to write data to bucket %q, file %q: %v", d.bucketName, fileName, err)
		return
	}
	if err := wc.Close(); err != nil {
		d.errorf("createFile: unable to close bucket %q, file %q: %v", d.bucketName, fileName, err)
		return
	}
}

ファイルが作成されると、このサンプルでは Cloud Storage ヘッダー(x-goog-meta-foo および x-goog-meta-bar)が指定されます。このオプションのコードでは、Cloud Storage ヘッダーを使用するという概念が導入されており、これは次のような目的で利用できます。

  • リクエストの動作に影響を与える。
  • Cloud Storage バケットでデフォルト以外のファイルへのアクセスを指定する。詳細については、x-goog-acl をご覧ください。
  • ファイルのメタデータを書き込む。

上記の x-goog-meta- ヘッダーは、設定可能なカスタム ファイルのメタデータであり、常にファイルとともに返されます。カスタム ヘッダーとそのデータに使用できるスペースは数キロバイトに制限されているため、注意して使用してください。

コードサンプルでは x-goog-acl は設定されていないため、デフォルトの Cloud Storage ACL の public read が、バケットへの書き込み時にオブジェクトに適用されます。

最後に、書き込みが完了した後にファイルを閉じる Close が呼び出されます。これを行わないと、ファイルは Cloud Storage に書き込まれません。Close を呼び出した後は、ファイルの内容を追加できないことに注意してください。

Cloud Storage からのファイルの読み取り

Cloud Storage からファイルを読み取るには:

// readFile reads the named file in Google Cloud Storage.
func (d *demo) readFile(fileName string) {
	io.WriteString(d.w, "\nAbbreviated file content (first line and last 1K):\n")

	rc, err := d.bucket.Object(fileName).NewReader(d.ctx)
	if err != nil {
		d.errorf("readFile: unable to open file from bucket %q, file %q: %v", d.bucketName, fileName, err)
		return
	}
	defer rc.Close()
	slurp, err := ioutil.ReadAll(rc)
	if err != nil {
		d.errorf("readFile: unable to read data from bucket %q, file %q: %v", d.bucketName, fileName, err)
		return
	}

	fmt.Fprintf(d.w, "%s\n", bytes.SplitN(slurp, []byte("\n"), 2)[0])
	if len(slurp) > 1024 {
		fmt.Fprintf(d.w, "...%s\n", slurp[len(slurp)-1024:])
	} else {
		fmt.Fprintf(d.w, "%s\n", slurp)
	}
}

バケットの内容を一覧表示する

このサンプルコードは、バケットの内容を一覧表示する方法を示しています。

// listBucket lists the contents of a bucket in Google Cloud Storage.
func (d *demo) listBucket() {
	io.WriteString(d.w, "\nListbucket result:\n")

	query := &storage.Query{Prefix: "foo"}
	it := d.bucket.Objects(d.ctx, query)
	for {
		obj, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			d.errorf("listBucket: unable to list bucket %q: %v", d.bucketName, err)
			return
		}
		d.dumpStats(obj)
	}
}

Cloud Storage ファイルのコピー

このサンプルコードは、バケットの内容を一覧表示する方法を示しています。

// copyFile copies a file in Google Cloud Storage.
func (d *demo) copyFile(fileName string) {
	copyName := fileName + "-copy"
	fmt.Fprintf(d.w, "Copying file /%v/%v to /%v/%v:\n", d.bucketName, fileName, d.bucketName, copyName)

	obj, err := d.bucket.Object(copyName).CopierFrom(d.bucket.Object(fileName)).Run(d.ctx)
	if err != nil {
		d.errorf("copyFile: unable to copy /%v/%v to bucket %q, file %q: %v", d.bucketName, fileName, d.bucketName, copyName, err)
		return
	}
	d.cleanUp = append(d.cleanUp, copyName)

	d.dumpStats(obj)
}

次のステップ

次のトピックで詳細をご覧ください。

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...

Go の App Engine スタンダード環境