SDK aws S3 Download to stdout

6,027 views
Skip to first unread message

Walter Garcia

unread,
Jun 29, 2016, 6:35:39 PM6/29/16
to golang-nuts
Hello all.

Im new using AWS SDK in go and Im need download file object from S3 to Stdout and not create a file.
For example:
my_download_s3_program > file.txt
or
my_download_s3_program | tar
etc

So, I can download to file, but I need stream on the fly to stdout, it's possible?

This example write a file:
----------------------------------------------------------------------
            file, err := os.Create("download_file.txt")
            if err != nil {
                fmt.Println("Failed to create file", err)
                os.Exit(4)
            }
            defer file.Close()

            key := path.Join(prefix, filename)

            downloader := s3manager.NewDownloader(session.New(&aws.Config{Region: aws.String("us-west-2")}))
            numBytes, err := downloader.Download(f,
                &s3.GetObjectInput{
                    Bucket: aws.String(bucket),
                    Key:    aws.String(key),
                })
            if err != nil {
                fmt.Println("Failed to download file", err)
                os.Exit(5)
            }

            fmt.Println("Downloaded file", file.Name(), numBytes, "bytes")

----------------------------------------------------------------------

How can modify this example to stream to stdout?

Well, thanks in advance.

Dave Cheney

unread,
Jun 29, 2016, 7:43:03 PM6/29/16
to golang-nuts
Try using os.Stdout as the download target.

Joshua Boelter

unread,
Jun 29, 2016, 11:53:31 PM6/29/16
to golang-nuts
I've been tinkering w/ the AWS Go SDK to get used to it ... this is one method using the GetObject API; see the full gist for a working example



s3Svc := s3.New(awsSession)

result, err := s3Svc.GetObject(&s3.GetObjectInput{
Bucket: aws.String(bucket),
Key:    aws.String(key),
})

if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}

n, err := io.Copy(os.Stdout, result.Body)
result.Body.Close()

Dave Cheney

unread,
Jun 29, 2016, 11:55:49 PM6/29/16
to golang-nuts
numBytes, err := downloader.Download(os.Stdout, &s3.GetObjectInput{ ... })

Should do it.

Walter Garcia

unread,
Jun 30, 2016, 1:17:22 PM6/30/16
to golang-nuts
I had already tried this option but does not work
this is the error

Failed to download file write /dev/stdout: illegal seek

Thanks in advance

Walter Garcia

unread,
Jun 30, 2016, 1:21:50 PM6/30/16
to golang-nuts
Excellent , this work fine

I attach the final sample code

            s3Svc := s3.New(session.New(&aws.Config{Region: aws.String("us-west-2")}))


            result, err := s3Svc.GetObject(&s3.GetObjectInput{
                Bucket: aws.String(bucket),
                Key:    aws.String(key),
            })

            if err != nil {
                fmt.Fprintln(os.Stderr, err)
                os.Exit(1)
            }

            io.Copy(os.Stdout, result.Body)
            result.Body.Close()

Thanks so much

Joshua Boelter

unread,
Jun 30, 2016, 10:16:39 PM6/30/16
to golang-nuts
If you want to use the s3manager Downloader to gain parallel/chunked downloads, you can use a temp buffer like so.  The seek error your getting is because it's using a io.WriterAt interface for io and pipes can't seek when you chain commands together (at least that I know of).


buff := &aws.WriteAtBuffer{}
s3dl := s3manager.NewDownloader(awsSession)
n, err := s3dl.Download(buff, &s3.GetObjectInput{
Bucket: aws.String(bucket),
Key:    aws.String(key),
})

if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}

n2, err := io.Copy(os.Stdout, bytes.NewReader(buff.Bytes()))
Reply all
Reply to author
Forward
0 new messages