Cloud Storage に対する読み取りと書き込み

このドキュメントでは、Cloud Storage クライアント ライブラリを使用してデータを保存、取得する方法を説明します。Cloud Storage の設定で説明されているように、Cloud Storage バケットを有効にし、クライアント ライブラリをダウンロードしておく必要があります。また、App Engine アプリケーションのビルド方法も理解している必要があります。

その他のコードサンプルについては、Cloud Storage クライアント ライブラリをご覧ください。

必要なインポート

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

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

次のスニペットに例を示します。

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"
)

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 ヘッダーを使用するという考え方が導入されており、次のような目的のために適用できます。

  • リクエストの動作に影響を与える。
  • デフォルトとは別のバケットにあるファイルへのアクセスを指定する(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 のファイルを削除する

以下のコードは、ObjectHandle.delete() メソッドを使用して Cloud Storage からファイルを削除する方法を示しています。


// deleteFiles deletes all the temporary files from a bucket created by this demo.
func (d *demo) deleteFiles() {
	io.WriteString(d.w, "\nDeleting files...\n")
	for _, v := range d.cleanUp {
		fmt.Fprintf(d.w, "Deleting file %v\n", v)
		if err := d.bucket.Object(v).Delete(d.ctx); err != nil {
			d.errorf("deleteFiles: unable to delete bucket %q, file %q: %v", d.bucketName, v, err)
			return
		}
	}
}

この例では、Cloud Storage に書き込むセクションでバケットに書き込んだファイルをクリーンアップしています。

次のステップ