Storing Files in S3 with Go

November 22nd 2018

This Go program uploads a file to an S3 bucket and then downloads and reads that same file from S3.

Want to read more posts like this? Subscribe to the blog! Sign in with Github

It's surprisingly difficult to find a straightforward tutorial on how to write to and read from S3. I need this in almost every language I utilize and in every language it has its own intricacies!

package main

import (
    "bytes"
    "fmt"
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/s3"
    "io"
    "net/http"
)

const S3_REGION = "us-west-2"
const S3_BUCKET = "your-bucket-here"

type S3Handler struct {
    Session *session.Session
    Bucket  string
}

func main() {
    sess, err := session.NewSession(&aws.Config{Region: aws.String(S3_REGION)})
    if err != nil {
        // Handle error
    }

    handler := S3Handler{
        Session: sess,
        Bucket:  S3_BUCKET,
    }

    err = handler.UploadFile("test-file", "This is a test file")
    if err != nil {
        // Handle error
    }

    contents, err := handler.ReadFile("test-file")
    if err != nil {
        // Handle error
    }

    fmt.Println(contents) // "This is a test file"
}

func (h S3Handler) UploadFile(key string, body string) error {
    buffer := []byte(body)

    _, err := s3.New(h.Session).PutObject(&s3.PutObjectInput{
        Bucket:               aws.String(h.Bucket),
        Key:                  aws.String(key),
        ACL:                  aws.String("private"),
        Body:                 bytes.NewReader(buffer),
        ContentLength:        aws.Int64(int64(len(buffer))),
        ContentType:          aws.String(http.DetectContentType(buffer)),
        ContentDisposition:   aws.String("attachment"),
        ServerSideEncryption: aws.String("AES256"),
    })

    return err
}

func (h S3Handler) ReadFile(key string) (string, error) {
    results, err := s3.New(h.Session).GetObject(&s3.GetObjectInput{
        Bucket: aws.String(h.Bucket),
        Key:    aws.String(key),
    })
    if err != nil {
        return "", err
    }
    defer results.Body.Close()

    buf := bytes.NewBuffer(nil)
    if _, err := io.Copy(buf, results.Body); err != nil {
        return "", err
    }
    return string(buf.Bytes()), nil
}

Gotchas

Be sure to either use the aws configure command via the AWS CLI or set the environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY before running your go application.

Also - Make sure to set the S3_BUCKET constant to a bucket you have created and have permission to write to and read from.

Want to read more posts like this? Subscribe to the blog! Sign in with Github