Ler e escrever no Cloud Storage

Este documento descreve como armazenar e obter dados através da biblioteca cliente do Cloud Storage. Pressupõe que concluiu as tarefas descritas em Configuração para o Cloud Storage para ativar um contentor do Cloud Storage e transferir as bibliotecas de cliente. Também pressupõe que sabe como criar uma aplicação do App Engine.

Para ver exemplos de código adicionais, consulte as bibliotecas de cliente do Cloud Storage

Importações necessárias

As importações no ficheiro necessárias para o App Engine e o Cloud Storage são:

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

como é mostrado no fragmento seguinte:

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

Especificar o contentor do Cloud Storage

Antes de poder executar qualquer operação do Cloud Storage, tem de fornecer o nome do contentor. A forma mais fácil de o fazer é usar o contentor predefinido para o seu projeto, que pode ser obtido a partir do contexto do App Engine, conforme mostrado neste fragmento:

// 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)
}

Escrever no Cloud Storage

Para escrever um ficheiro no 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
	}
}

Quando o ficheiro é criado, o exemplo especifica cabeçalhos do Cloud Storage (x-goog-meta-foo e x-goog-meta-bar). Este código opcional introduz a noção de usar cabeçalhos do Cloud Storage, que pode aplicar a:

  • Afetar o comportamento dos pedidos
  • Especificar o acesso ao ficheiro no contentor diferente das predefinições (consulte x-goog-acl)
  • Escrever metadados de ficheiros.

Os cabeçalhos x-goog-meta-* apresentados acima são metadados de ficheiros personalizados que pode definir. Estes cabeçalhos são sempre devolvidos com o ficheiro. Tenha em atenção que o espaço disponível para cabeçalhos personalizados e os respetivos dados está limitado a alguns kilobytes, pelo que deve usá-los com cuidado.

Uma vez que o exemplo de código não define x-goog-acl, a ACL do Cloud Storage predefinida de leitura pública é aplicada ao objeto quando é escrita no contentor.

Por fim, repare na chamada para Close() o ficheiro depois de terminar a escrita. Se não o fizer, o ficheiro não é escrito no Cloud Storage. Tenha em atenção que, depois de chamar Close(), não pode anexar nada ao ficheiro.

Ler a partir do Cloud Storage

Para ler um ficheiro do 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)
	}
}

Listar conteúdos de contentores

Este exemplo de código mostra como listar o conteúdo do contentor:

// 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)
	}
}

Eliminar ficheiros no Cloud Storage

O código abaixo demonstra como eliminar um ficheiro do Cloud Storage através do método ObjectHandle.delete().


// 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
		}
	}
}

Este exemplo limpa os ficheiros que foram escritos no contentor na secção Escrever no Cloud Storage.

O que se segue?