golang echoでgoogle cloud storageにファイルをuploadしてみる
はじめに
golangのフレームワークechoを使用してgoogle cloud storageにファイルをアップロードするAPIを作成してみた。 コードは後ほどgithubにあげる予定
google cloud storageと接続
Google Cloud Platform のサービスアカウントを取得し、gstorage/keysに保存する 今回は.envrcからファイル名を取得している gstorage/gstorage.go
package gstorage import ( "context" "log" "os" "github.com/pkg/errors" "cloud.google.com/go/storage" "google.golang.org/api/option" ) type googleStorage struct { client *storage.Client bucket string } // NewGoogleStorage mount google storage func NewGoogleStorage() GoogleStorage { ctx := context.Background() accountKey := os.Getenv("GCLOUD_ACCOUNT_KEY") if accountKey == "" { err := errors.New("Could not found google service account key") log.Fatal(err) } client, err := storage.NewClient(ctx, option.WithCredentialsFile("./gstorage/keys/"+accountKey)) if err != nil { log.Fatal(err) } return &googleStorage{ client: client, bucket: os.Getenv("GCLOUD_STORAGE_BUCKET"), } } // GoogleStorage google storage interface type GoogleStorage interface {}
main.goでgstorageの呼び出し main.go
func main() {
storage := gstorage.NewGoogleStorage()
}
gstorage.goにUploadメソッドを実装
gstorage/gstorage.go
// GoogleStorage google storage interface type GoogleStorage interface { Upload(file multipart.File, fileHeader *multipart.FileHeader, filePath string) (string, error) } func (gs *googleStorage) Upload(file multipart.File, fileHeader *multipart.FileHeader, filePath string) (string, error) { ctx := context.Background() sw := gs.client.Bucket(gs.bucket).Object(filePath + "/" + fileHeader.Filename).NewWriter(ctx) if _, err := io.Copy(sw, file); err != nil { return "", errors.New("Could not write file: " + err.Error()) } if err := sw.Close(); err != nil { return "", errors.New("Could not put file: " + err.Error()) } u, _ := url.Parse("/" + gs.bucket + "/" + sw.Attrs().Name) return "https://storage.googleapis.com" + u.EscapedPath(), nil }
controllerの実装
controller/controller.go
package controller import ( "net/http" "github.com/labstack/echo" "github.com/y-ogura/echo-google-cloud-storage/gstorage" ) // Controller controller type Controller struct { Storage gstorage.GoogleStorage } // NewController mount controller func NewController(e *echo.Echo, storage gstorage.GoogleStorage) { handler := &Controller{ Storage: storage, } e.GET("/", handler.InputForm) e.POST("/upload", handler.Upload) } // InputForm input form func (c *Controller) InputForm(ctx echo.Context) error { return ctx.HTML(http.StatusOK, formHTML) } // Upload upload file func (c *Controller) Upload(ctx echo.Context) error { file, fileHeader, err := ctx.Request().FormFile("file") if err != nil { return status.ResponseError(ctx, err) } defer file.Close() res, err := c.Storage.Upload(file, fileHeader, "filePath") if err != nil { return ctx.JSON(http.StatusInternalServerError, err) } return ctx.JSON(http.StatusOK, res) } const formHTML = `<!DOCTYPE html> <html> <head> <title>Storage</title> <meta charset="utf-8"> </head> <body> <form method="POST" action="/upload" enctype="multipart/form-data"> <input type="file" name="file"> <input type="submit"> </form> </body> </html>`
main.goでcontrollerを呼び出して環境を起動
main.go
func main() { e := echo.New() storage := gstorage.NewGoogleStorage() controller.NewController(e, storage) port := ":" + os.Getenv("PORT") e.Logger.Fatal(e.Start(port)) }