Video:

Uploading and Downloading Files from Our Bucket

March 19, 2018

Course Instructor: Elliot Forbes

Hey Gophers! My name is Elliot and I'm the creator of TutorialEdge and I've been working with Go systems for roughly 5 years now.

Twitter: @Elliot_f

We now have a bucket that we can effectively play with. In this video, we are going to look at how we can upload and download files to and from this newly created bucket.

package main

import (
	"fmt"
	"log"
	"os"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3/s3manager"
)

func main() {
	fmt.Println("Downloads and Uploads")
	sess, err := session.NewSession(&aws.Config{
		Region: aws.String("us-west-2"),
	})
	if err != nil {
		log.Fatal("Could not get session")
	}
}

With this session in place, we can then attempt to open our local file my-file.txt which is just a simple txt file. We then defer closing the file and then we create a new Uploader from the s3manager package that we’ve imported.

Once we have this new Uploader, we can then attempt to upload our image to the S3 bucket using the Upload function passing in our UploadInput object with our desired configuration:

func uploadItem(sess *session.Session) {
	f, err := os.Open("03-downloads-and-uploads/my-file.txt")
	if err != nil {
		log.Fatal("Could not open file")
	}
	defer f.Close()

	uploader := s3manager.NewUploader(sess)
	result, err := uploader.Upload(&s3manager.UploadInput{
		ACL:    aws.String("public-read"),
		Bucket: aws.String("go-aws-s3-course"),
		Key:    aws.String("my-file.txt"),
		Body:   f,
	})

	if err != nil {
		log.Fatal(err.Error())
	}

	log.Printf("Upload Result: %+v\n", result)
}

Note - The path to the file is the relative path from where you are executing the go run command. If you are running it from the same directory, you can change this to my-file.txt and run go run main.go.

With this in place, we can try and run our application now:

$ go run 03-downloads-and-uploads/main.go
Downloads and Uploads
2021/03/14 10:10:33 Upload Result: &{Location:https://go-aws-s3-course.s3.us-west-2.amazonaws.com/my-file.txt VersionID:<nil> UploadID: ETag:0xc000020bc0}

We should then see in the output the new location for this uploaded file! We can now hit the location within a browser and it should download our my-file.txt for us locally!

Listing Items in a Bucket

func listBucketItems(sess *session.Session) {
	svc := s3.New(sess)
	resp, err := svc.ListObjectsV2(
		&s3.ListObjectsV2Input{
			Bucket: aws.String("go-aws-s3-course"),
		},
	)
	if err != nil {
		log.Fatal(err.Error())
	}

	for _, item := range resp.Contents {
		fmt.Println("Name:         ", *item.Key)
		fmt.Println("Last modified:", *item.LastModified)
		fmt.Println("Size:         ", *item.Size)
		fmt.Println("Storage class:", *item.StorageClass)
		fmt.Println("")
	}
}

With this new function in place, let’s attempt to list out all of the items within our bucket by updating the main func:

func main() {
	fmt.Println("Downloads and Uploads")
	sess, err := session.NewSession(&aws.Config{
		Region: aws.String("us-west-2"),
	})
	if err != nil {
		log.Fatal("Could not get session")
	}

	uploadItem(sess)
	listBucketItems(sess)
}

And then running go run 03-downloads-and-uploads/main.go:

$ go run 03-downloads-and-uploads/main.go
Downloads and Uploads
2021/03/14 11:27:38 Upload Result: &{Location:https://go-aws-s3-course.s3.us-west-2.amazonaws.com/my-file.txt VersionID:<nil> UploadID: ETag:0xc00051c770}
Name:          my-file.txt
Last modified: 2021-03-14 11:27:39 +0000 UTC
Size:          12
Storage class: STANDARD

Perfect, as we can see, we are able to successfully upload our object and then see it within the list of objects in our bucket!

File Downloads

Now that we’ve populated our bucket with something, let’s try and download this newly uploaded file.

func downloadItem(sess *session.Session) {
	file, err := os.Create("03-downloads-and-uploads/downloaded.txt")
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()
	downloader := s3manager.NewDownloader(sess)

	// number of bytes downloaded or error
	_, err = downloader.Download(file,
		&s3.GetObjectInput{
			Bucket: aws.String("go-aws-s3-course"),
			Key:    aws.String("my-file.txt"),
		},
	)
	if err != nil {
		log.Fatal(err.Error())
	}
	log.Println("Successfully downloaded")
}

Perfect, we now have a function that will allow us to download our my-file.txt into a second file called downloaded.txt. Let’s try running this now:

$ go run 03-downloads-and-uploads/main.go
Downloads and Uploads
2021/03/14 11:27:38 Upload Result: &{Location:https://go-aws-s3-course.s3.us-west-2.amazonaws.com/my-file.txt VersionID:<nil> UploadID: ETag:0xc00051c770}
Name:          my-file.txt
Last modified: 2021-03-14 11:27:39 +0000 UTC
Size:          12
Storage class: STANDARD

2021/03/14 11:27:38 Successfully downloaded

If everything has gone to plan, we should see that our new file exists within the same directory as our main.go file and contains our Hello World! string!