AWS S3 (SDK v2) in Go Quickly example
Tags: go, s3, aws
Published: 2024-01-26 22:14:34

## Requirements
Get your AWS key and secrets from an Iam user in your AWS console and set as environments vars
```
AWS_KEY= <aws iam user key>
AWS_SECRET= <aws iam user secret>
```
Install the go dependencies

```
 go get github.com/aws/aws-sdk-go-v2
 go get github.com/aws/aws-sdk-go-v2/config
```
## Code
1. Create a struct for manage the AWS Client
It's a good practice to get this struct on an independent file to used if we want to implement mor3 AWS services.

File: manager.go
**Parameters:**
region: the AWS region (ex. us-east-1)
```
const AwsKeyEnv = "AWS_KEY"
const AwsSecretEnv = "AWS_SECRET"

type AwsConfigClient struct {
	config aws.Config
	region string
}

func NewAwsConfigClient(region string) (*AwsConfigClient, error) {
	key := os.Getenv(AwsKeyEnv)
	secret := os.Getenv(AwsSecretEnv)
	prov := credentials.NewStaticCredentialsProvider(key, secret, "")
	cfg, err := config.LoadDefaultConfig(context.TODO(),
		config.WithRegion(region),
		config.WithCredentialsProvider(prov),
	)
	if err != nil {
		return nil, err
	}
	return &AwsConfigClient{
		config: cfg,
	}, err
}
```
2. Create a struct for manager the common types.
File: s3.go
**Parameters:**
cfg : An instance from the struct config (step 1)
bucket: the name of the AWS Bucket
```
type AwsS3Client struct {
	config aws.Config
	bucket string
	s3     *s3.Client
}

func NewAwsS3Client(cfg *AwsConfigClient, bucket string) (*AwsS3Client, error) {
	client := s3.NewFromConfig(cfg.config)
	return &AwsS3Client{
		config: cfg.config,
		bucket: bucket,
		s3:     client,
	}, nil
}
```
### Upload a file to an AWS bucket
**Parameters:**
path : the path and the file we want to upload (example: /files/test.txt)
```
func (cli *AwsS3Client) UploadObject(path string) (*manager.UploadOutput, error) {
file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()
	client := s3.NewFromConfig(cli.config)
	uploader := manager.NewUploader(client)
	result, err := uploader.Upload(context.TODO(), &s3.PutObjectInput{
		Bucket: aws.String(cli.bucket),
		Key:    aws.String(filepath.Base(path)),
		Body:   file,
	})
	if err != nil {
		return nil, err
	}
	return result, nil
}

```
### Download a file from AWS bucket
**Parameters:** 
fileName : the name of the file in the AWS bucket

```
func (cli *AwsS3Client) Download(fileName string) (*manager.UploadOutput, error) {
	client := s3.NewFromConfig(cli.config)
	downloader := manager.NewDownloader(client)
	file, err := os.Create(fileName)
	if err != nil {
		return nil, err
	}
	defer file.Close()
	_, err = downloader.Download(context.TODO(), file, &s3.GetObjectInput{
		Bucket: aws.String(cli.bucket),
		Key:    aws.String(fileName),
	})
	return nil, nil
}
```
### Delete a file from AWS bucket
**Parameters:** 
fileName : the name of the file in the AWS bucket

```
func (cli *AwsS3Client) DeleteObject(fileName string) error {
	objectIds := []types.ObjectIdentifier{
		{Key: aws.String(fileName)},
	}
	_, err := cli.s3.DeleteObjects(context.TODO(), &s3.DeleteObjectsInput{
		Bucket: aws.String(cli.bucket),
		Delete: &types.Delete{Objects: objectIds},
	})
	return err
}
```

### Get the AWS files list

```
func (cli *AwsS3Client) GetObjects() ([]types.Object, error) {
	output, err := cli.s3.ListObjectsV2(context.TODO(), &s3.ListObjectsV2Input{
		Bucket: aws.String(cli.bucket),
	})
	if err != nil {
		return nil, err
	}
	data := make([]types.Object, len(output.Contents))
	for i, object := range output.Contents {
		data[i] = object
	}
	return data, nil
}
```
### GitHub code example
[AWS s3 files](https://github.com/luigiescalante/go-code-bucket/tree/main/awstools)

### Related links
[AWS S3 official documentation](https://aws.github.io/aws-sdk-go-v2/docs/sdk-utilities/s3/)
[AWS S3 official examples](https://github.com/aws/aws-sdk-go-v2/)