はじめに
GCSに画像を保存するのに結構ハマったので、簡単なサンプルでまとめる。1
「iOS/Swift+APIKit」と「GAE/Go+gin」のサンプルですが、ライブラリ等は適宜読み換えてください。
GAE/Go
前提
Google Cloud Storageのセットアップを済ませていること。
実装
エラーハンドリングは省略しています
gae.go
import (
"net/http"
"github.com/gin-gonic/gin"
)
func init() {
router := gin.Default()
http.Handle("/",getRouter())
}
func getRouter() *gin.Engine {
router := gin.Default()
router.GET("/upload/images", UploadImage)
return router
}
uploadImage.go
import (
"io/ioutil"
"cloud.google.com/go/storage"
"github.com/gin-gonic/gin"
"google.golang.org/appengine"
"google.golang.org/appengine/file"
)
func UploadImage(c *gin.Context) {
// 送られてきた画像データを取得する
fileHeader, err := c.FormFile("testImage")
imageFile, err := fileHeader.Open()
// appenigineのContextを取得
ctx := appengine.NewContext(c.Request)
// Storage上のbucket名を取得
bucket, err := file.DefaultBucketName(ctx)
// Storageを扱うclientを取得
client, err := storage.NewClient(ctx)
// Writerの生成
savePath := "hogehoge.png" //「icons/hoge.png」とか書ける
writer := client.Bucket(bucket).Object(savePath).NewWriter(ctx)
writer.ContentType = "image/png"
// []byteとして画像を取得
byteContainer, err := ioutil.ReadAll(imageFile) // ioutil.ReadXXXは重いので要注意
// 書き込み、保存する
_, err := wc.Write(byteContainer)
err = wc.Close()
}
画像のURL
画像ファイルのURLは、こんな感じで取れる
func GetUserImageURL(ctx context.Context, pathInBucket string) string {
const cloudStorageHOST = "https://storage.googleapis.com/"
projectID := appengine.AppID(ctx)
const projectDomain = ".appspot.com"
return cloudStorageHOST + projectID + projectDomain + "/" + pathInBucket
}
クライアント(iOS)
適当な画像をローカルのGAEにPOSTする。
nilチェックは省略しています。
main.swift
func uploadImage() {
let url = URL(string: "https://is1-ssl.mzstatic.com/image/thumb/Purple115/v4/f7/c4/0d/f7c40d38-759f-ae55-571a-3790b2d3aca5/source/0x0ss-85.png")!
let data = NSData(contentsOf: url)!
let request = SaveImageRequest(ImageData: data as Data)
Session.send(request) { result in print(result) }
}
SaveImageRequest.swift
// APIKit+Codableの構成
import APIKit
struct SaveImageResponse: Codable { //省略。受け取るレスポンスがあれば定義する }
struct SaveImageRequest: APIKit.Request {
typealias Response = SaveImageResponse
var ImageData: Data
let baseURL: URL = URL(string: "http://localhost:8080")!
var path: String {return "/upload/images"}
let method: APIKit.HTTPMethod = .post
var bodyParameters: BodyParameters? {
return MultipartFormDataBodyParameters(
parts: [MultipartFormDataBodyParameters.Part(
data: ImageData,
name: "testImage",
mimeType: "image/png",
fileName: "testImage.png")])
}
}
実行!
- **
gcloud auth login
とgcloud auth application-default login
**を叩き、認証を完了させる - バケットを指定してサーバーを起動
dev_appserver.py <app.yamlのpath> --default_gcs_bucket_name <バケット名>
- iOSからリクエストを送信 (あるいはcurl等)
- GCSをブラウザあるいはgsutilコマンドで確認し、画像が保存されているのを確かめる
参考
-
ちなみに、Google Blobstoreは非推奨となってる。 ↩