0

I am using the following code to download and upload the images from Amazon S3. Now, after downloading the image i want to resize it using the imagick library, but without writing it on to the disk. So, how do i create the image magick object directly from response stream which i will get from S3 and upload the same on Amazon S3. Could you please suggest the changes for the same in below code? Also, How do i change it to a http handler which takes the value of key from query string?

I have commented out my code of image magick object reason being i am sure how to write it.

func main() {
    file, err := os.Create("download_file")

        if err != nil {
            log.Fatal("Failed to create file", err)
        }
        defer file.Close()

        downloader := s3manager.NewDownloader(session.New(&aws.Config{Region: aws.String(REGION_NAME)}))
        numBytes, err := downloader.Download(file,
            &s3.GetObjectInput{
            Bucket: aws.String(BUCKET_NAME),
            Key:    aws.String(KEY),
            })
        if err != nil {
            fmt.Println("Failed to download file", err)
            return
        }

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

     //mw := imagick.NewMagickWand()
     //   defer mw.Destroy()

     //  err = mw.ReadImage(file)
     //  if err != nil {
     //      panic(err)
     //   }  
        // using io.Pipe read/writer file contents.
        reader, writer := io.Pipe()

        go func() {
        io.Copy(writer, file)

        file.Close()
        writer.Close()
        }()
        uploader := s3manager.NewUploader(session.New(&aws.Config{Region: aws.String(REGION_NAME)}))
        result, err := uploader.Upload(&s3manager.UploadInput{
        Body:   reader,
        Bucket: aws.String(BUCKET),
        Key:    aws.String(KEY),
        })

        if err != nil {
        log.Fatalln("Failed to upload", err)
        }

        log.Println("Successfully uploaded to", result.Location)
            fmt.Println("code ran successfully") 
}
Danack
  • 24,939
  • 16
  • 90
  • 122
Naresh
  • 5,073
  • 12
  • 67
  • 124
  • I don't see any image code in your example. Are you having trouble loading the image into imagick? Why are you downloading to a file if you don't want a file? – JimB Jan 27 '16 at 13:46
  • What is an "image magick object"? – Volker Jan 27 '16 at 14:23
  • @JimB If, I knew how to create the object from response stream.Why would i have asked the question. Anyways, I need to resize images on the fly. Since, Images are stored on S3. So, i need to download them on EC2 before that. So, to avoid the disk io i want to keep it in memory. Hence, asked this question how to create an image magick object from response stream in go lang. In the end why you downvoted my question? – Naresh Jan 27 '16 at 18:19
  • @Volker It's a library for image processing and it's wrapper in golang is called imagick. I have also provided the link in the question. By the way i didn't understand why you downvoted my question. – Naresh Jan 27 '16 at 18:22
  • ImageMagick doesn't operate on "streams", but it does refer to an image in memory as a "blob". To read an image from a `[]byte` you use `ReadImageBlob`. – JimB Jan 27 '16 at 18:25
  • @JimB I figured that out that there is an ReadImageBlob function in the library. But why would be the syntax for that. – Naresh Jan 27 '16 at 18:27
  • "What" would be the syntax? Instead of `ReadImage(file)`, you would use `ReadImageBlob(blob)`. Or, are you asking what to do after that? Or, How to get a new `[]byte` from the image without saving a file (`GetImageBlob`)? Or, just how to download into a `[]byte` (which has nothing to do with imagick). – JimB Jan 27 '16 at 19:06
  • @JimB I want to know how to download an image into `[ ]byte` and after that how do i create image magick object from the `[ ] byte`. So that i can do operations like cropping, resizing etc. – Naresh Jan 27 '16 at 19:18

1 Answers1

2

You only need a DownloadManager if you want to download large files more efficiently. A DownloadManager requires a WriterAt (generally an os.File), which you would have to implement yourself over a []byte or use a file in memory.

If you fetch the object directly, you can read it into a []byte which can be passed to ReadImageBlob:

out, err := s3Client.GetObject(&s3.GetObjectInput{
    Bucket: aws.String(BUCKET),
    Key:    aws.String(KEY),
})
if err != nil {
    log.Fatal(err)
}

img, err := ioutil.ReadAll(out.Body)
if err != nil {
    log.Fatal(err)
}

mw := imagick.NewMagickWand()
defer mw.Destroy()

err = mw.ReadImageBlob(img)
if err != nil {
    log.Fatal(err)
}
...
JimB
  • 104,193
  • 13
  • 262
  • 255