suguru.dev

バンクーバーで働くエンジニアの備忘録

GAEからCloud Storageに画像をアップロードする

はじめに

Google App Engine (GAE)のGolangAPI仕様がガラッと変わったようなので、古いバージョンを使っている方はここを参考に書き換えてください。

GitHub - golang/appengine: Go App Engine packages

Goのversionは1.6.2を使用しています。

画像のアップロード

実際はリクエストを受け取り、その画像をCloud Storageにアップロードしていますが、 実行しやすいようにローカルファイルとテストを使用しています。

package storage

import (
    "fmt"
    "google.golang.org/appengine"
    "google.golang.org/appengine/aetest"
    "google.golang.org/appengine/blobstore"
    "google.golang.org/appengine/image"
    "google.golang.org/appengine/log"
    "google.golang.org/cloud/storage"
    "io"
    "net/http"
    "os"
    "testing"
)

const (
    bucket = "<bucket path>"
    image = "<image path>"
)

func Upload(req *http.Request) (string, error) {
    ctx := appengine.NewContext(req)
    client, err := storage.NewClient(ctx)
    file, err := os.Open(image)
    userName := "tester"
    fileName := "test.jpg"
    mimeType := "image/jpeg"
    filePath := fmt.Sprintf("%s/%s", userName, fileName)
    blobWriter := client.Bucket(Bucket).Object(filePath).NewWriter(ctx)
    blobWriter.ContentType = mimeType
    io.Copy(blobWriter, file)
    err = blobWriter.Close()
    blobPath := fmt.Sprintf("/gs/%s/%s", Bucket, filePath)
    blobKey, err := blobstore.BlobKeyForFile(ctx, blobPath)

    // crop
    opts := image.ServingURLOptions{Secure: false, Crop: true}
    url, err := image.ServingURL(ctx, blobKey, &opts)
    log.Infof(ctx, "url", url)
    return url.String(), err
}

func TestUpload(t *testing.T) {
    inst, err := aetest.NewInstance(nil)
    req, err := inst.NewRequest("GET", "/gophers", nil)
    url, err := Upload(req)
    fmt.Printf("test", url, err)
}

ローカルで実行すると画像は正常にアップロードされますが、ServingURLがうまく働いてくれないようでhttp://localhost/_ah/img/encoded_gs_file:...のようなパスになってしまいます。 GAE上だと正常に動いているのですがテストを書く上でとても不便ですね。。