image.Decode results in "unknown format" when source is multipart.File
Asked Answered
H

1

5

I have a multipart.File that a user uploads to my server, and then I take that file and upload it to s3 using aws-sdk-go, but I also want to create a thumbnail of that image.

The code below works fine in my tests when I file is the return value of an os.Open(... of a local file, but it hit's the err block when I send CreateThumbnail the same variable I sent to s3, which asks for an io.Reader

import (
  "image"
  "image/jpeg"
)
func UploadToS3(file multipart.File, /*snip*/) {
  _, uploadErr := uploader.Upload(&s3manager.UploadInput{
    Bucket: aws.String(bucket),
    Key:    aws.String(key),
    Body:   file,
    ContentType: aws.String(mimeType),
    ACL: aws.String("public-read"),
  })
  reader, err := CreateThumbnail(file)
}    

func CreateThumbnail(imageFile io.Reader) (io.Reader, error) {
  decodedImage, _, err := image.Decode(imageFile)
  if err != nil {
   fmt.Println("Error decoding", err, decodedImage) // "unknown format"
   return nil, err
 }
 /*snip*/

Most of the answers I see for the problem involve adding import _ "image/jpeg", but that's already imported (as well as png and gif). I'm fairly new to Golang, so I'm a bit lost as to what I'm doing wrong. I tried image.Decode(bufio.NewReader(imageFile)) as well, but that results in the same err.

Hawn answered 17/6, 2015 at 15:34 Comment(3)
You could debug this by making sure the multipart.File really is a jpeg: Check the first handful of bytes.Indecision
@Indecision It's not, the first 2 bytes are not 'FF D8'. I can send that variable to s3 and it get's saved as an image, how can I do the same locally without image.Decode(imageFile)?Hawn
No idea. If you could post the let's say first 100 bytes someone might recognise it.Indecision
M
9

The call uploader.Upload reads to the end of the file. Seek back to the beginning of the file before calling CreateThumbnail:

func UploadToS3(file multipart.File, /*snip*/) {
  _, uploadErr := uploader.Upload(&s3manager.UploadInput{
    Bucket: aws.String(bucket),
    Key:    aws.String(key),
    Body:   file,
    ContentType: aws.String(mimeType),
    ACL: aws.String("public-read"),
  })
  // Seek back to beginning of file for CreateThumbnail
  if _, err := file.Seek(0, 0); err != nil {
    // handle error
  }
  reader, err := CreateThumbnail(file)
}    
Mealtime answered 18/6, 2015 at 5:40 Comment(1)
This work as long as I changed the parameter type to multipart.File (since that implements io.Reader and io.Seeker). Thanks @ThunderCatHawn

© 2022 - 2024 — McMap. All rights reserved.