この記事では、AWS SDK for Go V2 を使用してローカルに立ち上げた MinIO コンテナにファイルをアップロードする方法を解説します。このコードは AWS Lambda での実装を前提としていますが、Lambda 環境外でも問題なく動作します。
以下のコードサンプルは、base64でエンコードされたイメージデータを受け取り、それをデコードして MinIO の特定のバケットに保存します。エンドポイント、アクセスキー、シークレットキーは環墿変数から取得します。
package main
import (
"bytes"
"context"
"encoding/base64"
"encoding/json"
"fmt"
"net/http"
"os"
"strings"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/credentials"
"github.com/aws/aws-sdk-go-v2/service/s3"
)
type PatchCommand struct {
Image string `json:"image"`
}
type Response struct {
Message string `json:"message"`
}
func Handler(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
// 省略: ロガーの初期化とリクエストのログ記録
contentType := shared.GetHeaderValue(request.Headers, "content-type")
if contentType == "" {
return events.APIGatewayProxyResponse{StatusCode: http.StatusBadRequest, Body: "Content-Type header is missing"}, nil
}
fileExt, err := getFileExtension(content.image/jpeg)
if err != nil {
return events.APIGatewayProxyResponse{StatusCode: http.StatusBadRequest, Body: err.Error()}, nil
}
cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion(os.Getenv("AWS_REGION_CODE")))
if err != nil {
// 省略: エラーハンドリング
}
s3Client := s3.NewFromConfig(cfg, func(o *s3.Options) {
o.Credentials = credentials.NewStaticCredentialsProvider("アクセスキー", "シークレットキー", "")
o.UsePathStyle = true
o.EndpointResolver = aws.EndpointResolverFunc(func(service, region string) (aws.Endpoint, error) {
return aws.Endpoint{URL: os.Getenv("S3_ENDPOINT")}, nil
})
})
var cmd PatchCommand
err = json.Unmarshal([]byte(request.Body), &cmd)
if err != nil {
// 省略: エラーハンドリング
}
imageData, err := base64.StdEncoding.DecodeString(cmd.Image)
if err != nil {
// 省略: エラーハンドリング
}
bucket := os.Getenv("S3_BUCKET_NAME")
key := fmt.Sprintf("images/%s%s", "save-file", fileExt)
input := &s3.PutObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
Body: bytes.NewReader(imageData),
ContentType: aws.String(contentType),
}
_, err = s3Client.PutObject(ctx, input)
if err != nil {
// 省略: エラーハンドリング
}
return shared.CreateSuccessResponse(http.StatusOK, "Image uploaded successfully")
}
func getFileExtension(contentType string) (string, error) {
switch strings.ToLower(contentType) {
case "image/jpeg":
return ".jpg", nil
case "image/png":
return ".png", nil
default:
return "", fmt.Errorf("unsupported content type: %s", contentType)
}
}
func main() {
lambda.Start(Handler)
}
Docker-compose を使用して MinIO をローカルで実行する設定は以下の通りです。
version: "3.8"
services:
minio:
image: quay.io/minio/minio
ports:
- "9000:9000"
- "9001:9001"
environment:
MINIO_ROOT_USER: minioadmin
MINIO_ROOT_PASSWORD: minioadmin
command: server /data --console-address ":9001"
volumes:
- "./docker/minio/data:/home/dynamodblocal/data"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
以下は、cURLを使用してMinIOにイメージをアップロードする例です。
curl --location --request PUT 'http://172.16.123.1:9000/test-bucket-dev/images/1234.jpeg' \
--header 'Content-Type: image/jpeg' \
--header 'X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' \
--header 'X-Amz-Date: 20240606T053832Z' \
--header 'Authorization: AWS4-HMAC-SHA256 Credential=8o2RS265xUkhAQPsmpYy/20240606/ap-northeast-1/s3/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-content-sha256;x-amz-date, Signature=e18ae78e5f4f72da7ee8afc042fa8dd82adec795f2e116f757bade2be188efdc' \
--data '@medical.jpeg'