環境
インストール
$ dep ensure -add github.com/aws/aws-sdk-go
ファイル構成
- path/to/go/src/psychedelicnekopunch/go-sample/
infrastructure/
├ AwsS3.go
└ Config.go
images/
└ sample.png
main.go
サンプルコード
infrastructure/Config.go
package infrastructure
type Config struct {
Aws struct {
S3 struct {
Region string
Bucket string
AccessKeyID string
SecretAccessKey string
}
}
}
func NewConfig() *Config {
c := new(Config)
// ex) アジアパシフィック (東京): ap-northeast-1
c.Aws.S3.Region = "ap-northeast-1"
c.Aws.S3.Bucket = "YOUR Bucket Name"
c.Aws.S3.AccessKeyID = "YOUR AWS Access key ID"
c.Aws.S3.SecretAccessKey = "YOUR AWS Secret Access Key"
return c
}
infrastructure/AwsS3.go
package infrastructure
import (
"errors"
"fmt"
"mime/multipart"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
)
type AwsS3 struct {
Config *Config
Keys AwsS3URLs
Uploader *s3manager.Uploader
}
type AwsS3URLs struct {
Test string
}
func NewAwsS3() *AwsS3 {
config := NewConfig()
// The session the S3 Uploader will use
sess := session.Must(session.NewSessionWithOptions(session.Options{
Config: aws.Config{
// Access key ID と Secret Access Key は IAM から作成する。
// 一度作成した Access key ID の Secret Access Key は csv ファイルでダウンロードしていない場合は、
// 確認する手段がないので新しくアクセスキーを作成する必要がある。
Credentials: credentials.NewStaticCredentialsFromCreds(credentials.Value{
AccessKeyID: config.Aws.S3.AccessKeyID,
SecretAccessKey: config.Aws.S3.SecretAccessKey,
}),
Region: aws.String(config.Aws.S3.Region),
},
}))
return &AwsS3{
Config: config,
Keys: AwsS3URLs{
Test: "test/images",
},
// Create an uploader with the session and default options
Uploader: s3manager.NewUploader(sess),
}
}
func (a *AwsS3) UploadTest(file multipart.File, fileName string, extension string) (url string, err error) {
if fileName == "" {
return "", errors.New("fileName is required")
}
var contentType string
switch extension {
case "jpg":
contentType = "image/jpeg"
case "jpeg":
contentType = "image/jpeg"
case "gif":
contentType = "image/gif"
case "png":
contentType = "image/png"
default:
return "", errors.New("this extension is invalid")
}
// Upload the file to S3.
result, err := a.Uploader.Upload(&s3manager.UploadInput{
// ACL の設定は重要
ACL: aws.String("public-read"),
Body: file,
Bucket: aws.String(a.Config.Aws.S3.Bucket),
// content-type の設定も忘れずに
ContentType: aws.String(contentType),
Key: aws.String(a.Keys.Test + "/" + fileName + "." + extension),
})
if err != nil {
return "", fmt.Errorf("failed to upload file, %v", err)
}
return result.Location, nil
}
使いかた
main.go
- path/to/go/src/psychedelicnekopunch/go-sample/images/sample.png を s3 に test.png というファイル名でアップロードする。
package main
import (
"fmt"
"os"
"psychedelicnekopunch/go-sample/infrastructure"
)
func main() {
var (
file *os.File
err error
awsS3 *infrastructure.AwsS3
url string
)
// このファイルと同じ階層に images/sample.png がある想定
file, err = os.Open("images/sample.png")
if err != nil {
fmt.Printf(err.Error())
return
}
defer file.Close()
awsS3 = infrastructure.NewAwsS3()
// multipart.File と os.File は同じように扱える
url, err = awsS3.UploadTest(file, "test", "png")
if err != nil {
fmt.Print(err.Error())
return
}
fmt.Print(url)
}
go 製フレームワーク gin を用いた使いかた
main.go
- <input type="file" name="uploadImage"> でアップロード。
- gin を用いた API のファイル構成の話はここでは割愛。
package main
import (
"github.com/gin-gonic/gin"
"psychedelicnekopunch/go-sample/infrastructure"
)
func main() {
g := gin.Default()
g.POST("/uploads", func (c *gin.Context) {
awsS3 := infrastructure.NewAwsS3()
// func (c *gin.Context) FormFile(name string) (*multipart.FileHeader, error)
fileHeader, err := context.FormFile("uploadImage")
if err != nil {
c.JSON(400, gin.H{ "message": err.Error() })
}
// func (fh *FileHeader) Open() (multipart.File, error)
file, err := fileHeader.Open()
if err != nil {
c.JSON(400, gin.H{ "message": err.Error() })
}
url, err = awsS3.UploadTest(file, "test", "png")
if err != nil {
c.JSON(400, gin.H{ "message": err.Error() })
}
c.JSON(201, gin.H{ "message": "success" })
})
g.Run(":8080")
}