📚

API Gateway にmultipart/form-dataでファイルアップロードしたかった話

2021/09/13に公開

ある日、私はAWS Serverless Application Model(SAM)でGoファイルをアップロードしてastを返してくれるAPIを作ろうとしていました

main.go
package main

import (
        "fmt"
)

func main() {
        fmt.Println("Wow!")
}

上記のファイルをmultipart/form-dataで下のように送信しました。

file: main.go
description: "nice to meet you !"

そして、おもむろにrequest.Bodyを取り出すと、、、

main.go

func main() {
  lambda.Start(start)
}

func start(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
  // ここ
  println(request.Body)
}
ターミナル(結果)
----------------------------407965267923073511136631
Content-Disposition: form-data; name="file"; filename="main.go"
Content-Type: application/octet-stream

package main

import (
        "fmt"
)

func main() {
        fmt.Println("Wow!")
}

----------------------------407965267923073511136631
Content-Disposition: form-data; name="description"

nice to meet you !
----------------------------407965267923073511136631--

stringやんけ...

だから公式ではファイル送信時にbase64で送れいうとったんか...

...

でも、どうしてもファイルを送信したかったのでmultipart/form-data形式の文字列を読み込むパッケージを作りました🎉

https://github.com/gari8/shuttle

go get github.com/gari8/shuttleとかでインストールできます。

これはめちゃくちゃ薄いパッケージなのですが、multipart/form-dataの文字列を読み込んでname属性を指定して値を取り出すものです。

今回の場合main.goで使うと下記のようになります。

main.go
import (
  ...
  "github.com/gari8/shuttle"
)

const (
  boundary = "---------------------------"
)

func main() {
  lambda.Start(start)
}

func start(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
  // ここでmultipart文字列を第一引数に、バウンダリー文字列(------こんな感じのやつ)を第二引数に渡す
  sh := shuttle.New(request.Body, boundary)
  // 見たいものを指定
  fmt.Println(sh.Launch("description"))
  fmt.Println(sh.Launch("file"))
}
ターミナル(結果)
nice to meet you !
package main

import (
        "fmt"
)

func main() {
        fmt.Println("Wow!")
}

以下のようにdescriptionfileそれぞれの値を取り出せます!

使う場面はあまりなさそうですが、誰かの助けになれば幸いです!

Discussion