Upload files to Amazon S3 with Golang
Tags: go, aws, s3
Published: 2019-11-01 17:27:27

---
title: "Upload files to Amazon S3 with Golang"
description: "Example of connecting, uploading, downloading, and listing files from an AWS S3 Bucket with Golang."
published: true
canonical_url: https://asanchez.dev/blog/upload-to-amazon-s3-with-golang/
tags: 
  - Go
  - AWS
  - S3
---
Connecting your Go application with <a href="https://aws.amazon.com/s3/" target="_blank">Amazon S3</a> is pretty easy and requires only a few lines of code. But if you have no experience with Amazon Web Services, it can get pretty tricky at the beginning to figure out even the most straightforward task. 

We are going to see here how to connect to S3 with Golang, upload a file from a form to an S3 bucket, download it, and list all items saved on this bucket. 

I am going to suppose that you have already:
- created an AWS account
- created an Amazon Simple Storage (S3) Bucket
- generated the credentials to access it (Access key ID and Secret access key)

I am not going to explain those things here since there are already plenty of good tutorials on the Internet about it.

## Set up your credentials
After having created the S3 Bucket, the very first thing that we are going to do is to save the credentials. 

There are a few ways of doing this as described here https://docs.aws.amazon.com/es_es/sdk-for-go/v1/developer-guide/configuring-sdk.html 

We are going to use the easiest one using a shared credential file. For this, create a file like described below on `~/.aws/credentials` on Linux, macOS or Unix. If using windows, create it on `C:\Users\USERNAME\.aws\credential`.  

```
[default] 
aws_access_key_id = your_access_key_id 
aws_secret_access_key = your_secret_access_key
```

## Install the SDK
After this, we need to install de AWS SDK for Go:
 
```go
go get -u github.com/aws/aws-sdk-go/...
```
and import the AWS packages into your Go application:

```go
import ( 
    "github.com/aws/aws-sdk-go/aws" 
    "github.com/aws/aws-sdk-go/aws/session" 
    "github.com/aws/aws-sdk-go/service/s3"
)
``` 

## The Code
You can skip all explanations below and check the code directly on https://github.com/antsanchez/goS3example. 

I have tried to keep the code as minimal as possible. 

## Connect to AWS S3
I like to use this code on my main.go file or whatever other file where I can share the session (``sess`` variable) to reuse it.

```go
const (
	AWS_S3_REGION = ""
	AWS_S3_BUCKET = ""
)

var sess = connectAWS()

func connectAWS() *session.Session {
	sess, err := session.NewSession(
            &aws.Config{
                Region: aws.String(AWS_S3_REGION)
            }
        )
	if err != nil {
		panic(err)
	}
	return sess
}
```

## Upload a file from a form to Amazon S3
First, get the file from the form:
```go
file, header, err := r.FormFile("file")
if err != nil {
    // Do your error handling here
    return
}
defer file.Close()

filename := header.Filename
```

Then, upload it to S3:

```go
uploader := s3manager.NewUploader(sess)

_, err = uploader.Upload(&s3manager.UploadInput{
    Bucket: aws.String(AWS_S3_BUCKET), // Bucket to be used
    Key:    aws.String(filename),      // Name of the file to be saved
    Body:   file,                      // File
})
if err != nil {
    // Do your error handling here
    return
}
```

## Download a file from Amazon S3
First, create a temporary file where to store the downloaded file:

```go
f, err := os.Create(filename)
if err != nil {
    // Do your error handling here
    return
}
```

Now, download the file and do whatever you want with it (``f``)
```go
downloader := s3manager.NewDownloader(sess)
_, err = downloader.Download(f, &s3.GetObjectInput{
    Bucket: aws.String(AWS_S3_BUCKET),
    Key:    aws.String(filename),
})
if err != nil {
    // Do your error handling here
    return
}
```

## List the items of an AWS S3 Bucket
```go 
svc := s3.New(sess)
input := &s3.ListObjectsInput{
    Bucket: aws.String(AWS_S3_BUCKET),
}

result, err := svc.ListObjects(input)
if err != nil {
    if aerr, ok := err.(awserr.Error); ok {
        switch aerr.Code() {
        case s3.ErrCodeNoSuchBucket:
            fmt.Println(s3.ErrCodeNoSuchBucket, aerr.Error())
        default:
            fmt.Println(aerr.Error())
        }
    } else {
        // Print the error, cast err to awserr.Error to get the Code and
        // Message from an error.
        fmt.Println(err.Error())
    }
    // Do your error handling here
    return
}
```

You could now list the items showing the name like this:

```go
w.Header().Set("Content-Type", "text/html")

for _, item := range result.Contents {
    fmt.Fprintf(w, "<li>File %s</li>", *item.Key)
}
```

## More information
There are plenty of tutorials on internet, but not all of them are updated or following the best practices. 
I would recommend you to check those links:

- [Getting Started with the AWS SDK for Go](https://docs.aws.amazon.com/es_es/sdk-for-go/v1/developer-guide/setting-up.html)
- [Configuring the AWS SDK for Go](https://docs.aws.amazon.com/es_es/sdk-for-go/v1/developer-guide/configuring-sdk.html)

And that's all.