🤖
Goでmultipart.fileheader型の画像をFormから複数受け取ってDBに保存する
環境
- go1.18.3
- gorm.io/gorm v1.23.8
- gorm.io/driver/mysql v1.3.5
実装
package model
type Image struct {
Id int
Source []byte `json:"source" gorm:"size:70000"`
}
package database
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
"example.com/model"
)
var db *gorm.DB
func DbConn() {
dsn := "root:hoge@tcp(127.0.0.1:3306)/todo?charset=utf8mb4&parseTime=True&loc=Local"
db, _ = gorm.Open(mysql.Open(dsn), &gorm.Config{})
db.AutoMigrate(&model.Todo{}, &model.Image{})
}
func Create(obj interface{}) {
db.Create(obj)
}
package imagecontroller
import(
"fmt"
"net/http"
"io"
"example.com/database"
"example.com/model"
)
func Create(w http.ResponseWriter, r *http.Request){
r.ParseMultipartForm(32 << 20)
mf := r.MultipartForm
images := mf.File["images[]"]
for _, image := range images {
fmt.Printf("%T\n", image) // *multipart.FileHeader
data, _ := image.Open()
source, _ := io.ReadAll(data)
fmt.Printf("%T\n", source) // []uint8
image := model.Image { Source: source}
database.Create(&image)
}
}
解説
- net/httpでmultipart.Formを扱うためにr.ParseMultipartFormを宣言し、
r.MultipartForm("key名")で値を取得する。
r.ParseMultipartForm(32 << 20)
mf := r.MultipartForm
images := mf.File["images[]"]
https://pkg.go.dev/net/http
// MultipartForm is the parsed multipart form, including file uploads.
// This field is only available after ParseMultipartForm is called.
// The HTTP client ignores MultipartForm and uses Body instead.
MultipartForm *multipart.Form
- mysqlに画像を保存するためには*multipart.FileHeaderからbinaryに変換する必要があるので、ioパッケージのReadAll関数を利用する。
multipart.FileHeaderはio.Readerを持っていないので、
Open関数でFileに変換してからReadAll関数の引数に渡す。
for _, image := range images {
fmt.Printf("%T\n", image) // *multipart.FileHeader
data, _ := image.Open()
source, _ := io.ReadAll(data)
fmt.Printf("%T\n", source) // []uint8
image := model.Image { Source: source}
database.Create(&image)
}
まとめ
画像を直接DBに保存するとネットワークとDBに結構負荷がかかってしまうので、
パフォーマンスを考えると、S3などのオブジェクトストレージを使って、
相対パスをDBで管理するとかが良い。
Discussion