見出し画像

Go言語によるAmazon S3実装ガイド

この記事は弊社のITエンジニア:Bishal Bhattarai が作成した記事です。英語版はこちらをご覧ください。
Medium

Amazon Simple Storage Service (S3) は、開発者がいつでも任意の量のデータを保存および取得できる、広く利用されているクラウドストレージソリューションです。このガイドでは、AWS SDK for Go V2 を使用して Go (Golang) アプリケーションに Amazon S3 を統合する方法を順を追って説明します。このチュートリアルでは、AWS 認証情報の設定、ファイルのアップロード、事前署名済み URL の生成、Go 言語での権限処理について取り上げます。さらに、チュートリアルでは AWS コンソールから効果的な S3 バケットを設定する方法もガイドします。Enter キーを押すかクリックして画像をフルサイズで表示

前提条件

開始前に、以下の準備が整っていることを確認してください:

  • AWSアカウント:S3へのアクセス権限を持つ有効なAWSアカウント。

  • AWS認証情報:AWS CLIまたは環境変数を使用してAWS認証情報を設定してください。

  • Go環境:Go(バージョン1.15以降)がインストールされていること。

Goプロジェクトを初期化してください。

go mod init fileuploader

Install required dependencies for go v2

go get github.com/aws/aws-sdk-go-v2/aws

go get github.com/aws/aws-sdk-go-v2/configgo get github.com/aws/aws-sdk-go-v2/credentialsgo get github.com/aws/aws-sdk-go-v2/feature/s3/managergo get github.com/aws/aws-sdk-go-v2/service/s3

AWS S3 バケットの設定

AWS コンソールにアクセスし、S3を検索します。
バケットを作成します。
Enterキーを押すかクリックして画像をフルサイズで表示します。

Enterキーを押すかクリックして画像をフルサイズで表示

Press enter or click to view image in full size

バケット作成後、AWSプログラムアクセスユーザーに対するアクセスポリシーを設定する必要があります。そのためには、バケットの詳細画面の「権限」セクションに移動し、バケットポリシーを追加します。Enterキーを押すか、画像をクリックしてフルサイズで表示してください。

{
    "Version": "2012-10-17",
    "Id": "Policy1741260717481",
    "Statement": [
        {
            "Sid": "Stmt1741260713124",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::047719652545:user/cli-user"
            },
            "Action": [
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "arn:aws:s3:::trouble-storage-bucket",
                "arn:aws:s3:::trouble-storage-bucket/*"
            ],
            "Condition": {
                "StringEquals": {
                    "s3:x-amz-acl": "public-read"
                }
            }
        }
    ]
}

オブジェクトの所有権については、ACLを有効にする必要があります。Enterキーを押すかクリックして画像をフルサイズで表示してください

書き込みアクセス権を持つバケットの作成に成功しました。次に、Go言語におけるAWS S3の実装コードを見ていきましょう。

Go言語でのAWS S3設定

ステップ1: AWS SDKとS3クライアントの初期化

AWS SDKを設定し、S3クライアントを初期化するinit関数を作成します。

package main

import (
 "context"
 "fmt"
 "log"
 "mime/multipart"
 "net/http"
 "os"
 "time"

 "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/feature/s3/manager"
 "github.com/aws/aws-sdk-go-v2/service/s3"
)

const (
 BucketName = "storagebucket"
 Region     = "region"
 AccessKey  = "Access_key"
 SecretKey  = "Secret Key"
)

var uploader *manager.Uploader
var client *s3.Client

func init() {
 cfg, err := config.LoadDefaultConfig(context.TODO(),
  config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(
   AccessKey,
   SecretKey,
   "",
  )),
  config.WithRegion(Region),
 )
 if err != nil {
  log.Fatalf("Failed to load AWS SDK config: %v", err)
 }

 // Create S3 client and uploader gloabally so it can be used.
 client = s3.NewFromConfig(cfg)
 uploader = manager.NewUploader(client)
}

ステップ2: S3へのファイルアップロード

関数`uploadFileToS3`はファイルを受け取り、指定されたS3バケットにアップロードします。

func uploadFileToS3(file multipart.File, fileHeader *multipart.FileHeader) (string, error) {
 // Upload input
 uploadInput := &s3.PutObjectInput{
  Bucket:      aws.String(BucketName),
  Key:         aws.String(fileHeader.Filename),
  Body:        file,
  ContentType: aws.String(fileHeader.Header.Get("Content-Type")),
 }

 // Upload file
 result, err := uploader.Upload(context.TODO(), uploadInput)
 if err != nil {
  return "", fmt.Errorf("failed to upload file to S3: %w", err)
 }

 // getsigned url
 fmt.Println("result.Location ::", *result.Key)
 url, err := GetPresignedURL(fileHeader.Filename)
 return url, nil
}

ステップ3: 事前署名済みURLの生成

事前署名済みURLを使用すると、認証情報を公開することなく、S3オブジェクトへの一時的なアクセスが可能になります。


func GetPresignedURL(fileName string) (string, error) {
 presigner := s3.NewPresignClient(client)
 // Generate a pre-signed URL for PUT (upload)
 presignedReq, err := presigner.PresignGetObject(context.TODO(), &s3.GetObjectInput{
  Bucket: aws.String(BucketName),
  Key:    aws.String(fileName),
 }, s3.WithPresignExpires(15*time.Minute)) // URL expires in 15 minutes

 if err != nil {
  return "", fmt.Errorf("failed to create presigned URL: %w", err)
 }
 fmt.Println("presignedURL ::", presignedReq.URL)

 return presignedReq.URL, nil
}

ステップ4: 簡易HTTPサーバーの実行

HTTPリクエストによるファイルアップロードを受け付けるには、アップロードハンドラーを作成し、HTTPサーバーを起動します。

func main() {
 http.HandleFunc("/upload", UploadHandler)

 port := os.Getenv("PORT")
 if port == "" {
  port = "8080"
 }
 log.Println("Server running on port:", port)
 log.Fatal(http.ListenAndServe(":"+port, nil))
}

以下はアップロードAPIのアップロードハンドラーです

// UploadHandler handles file upload to S3
func UploadHandler(w http.ResponseWriter, r *http.Request) {
 if r.Method != http.MethodPost {
  http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
  return
 }

 // Parse the multipart form
 err := r.ParseMultipartForm(10 << 20) // 10 MB max file size
 if err != nil {
  http.Error(w, "Failed to parse form", http.StatusBadRequest)
  return
 }

 // Retrieve the file
 file, fileHeader, err := r.FormFile("file")
 if err != nil {
  http.Error(w, "Failed to get file", http.StatusBadRequest)
  return
 }
 defer file.Close()

 // Upload file to S3
 fileURL, err := uploadFileToS3(file, fileHeader)
 if err != nil {
  fmt.Println("Error ::", err.Error())
  http.Error(w, "Failed to upload file to S3", http.StatusInternalServerError)
  return
 }

 // Return the file URL
 w.WriteHeader(http.StatusOK)
 fmt.Fprintf(w, `{"message": "File uploaded successfully", "url": "%s"}`, fileURL)
}

プロジェクトを実行してくださいgo run fileuploader.goEnterキーを押すかクリックして画像をフルサイズで表示

以下はPostmanでのAPI呼び出しですEnterキーを押すかクリックして画像をフルサイズで表示

おめでとうございます!AWS S3とGoの統合に成功しました。このチュートリアルでは以下の内容を扱いました:

  • AWSでのS3設定

  • Go言語コードをS3バケットに実装
    S3バケットへのファイルアップロード
    安全なアクセス用事前署名済みURLの生成
    HTTPファイルアップロードの処理

これらの手順を実装することで、Goアプリケーションにおけるファイルのアップロードと取得を効率的に管理できます。

プログラミングを楽しんでください

参考:https://github.com/bhattaraibishal50/aws-s3-uploader


協業開発及び開発パートナーをお探しのお客様へ

弊社は、ネパールに海外拠点を持ち、生成AI、モバイルアプリ、システム開発を中心に事業を展開する企業です。
自社サービスの開発経験を活かし、クライアント様と共に事業を創造することを重視し、創業以来、スタートアップから中小企業、大手企業、自治体まで、幅広い開発実績があります。プロダクトはユーザーが使いやすいように設計しており、企画から開発、保守運用まで対応しています。開発技術を厳選し限定することで、セキュリティ、プロダクトの品質向上に努めており、事業開発に関する課題を深く理解し、最適なご提案が可能です
お問い合わせはこちらから:
お問い合わせフォーム:https://readytowork.jp/
直通番号:080-8940-7169