LoginSignup
2

More than 5 years have passed since last update.

iOS/Swiftで画像を送信し、GAE/GoからGCSに画像を保存する

Last updated at Posted at 2018-06-30

はじめに

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

実行!

0) gcloud auth logingcloud auth application-default loginを叩き、認証を完了させる
1) バケットを指定してサーバーを起動
dev_appserver.py <app.yamlのpath> --default_gcs_bucket_name <バケット名>
2) iOSからリクエストを送信 (あるいはcurl等)
3) GCSをブラウザあるいはgsutilコマンドで確認し、画像が保存されているのを確かめる

参考


  1. ちなみに、Google Blobstoreは非推奨となってる。 

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
2