Golang无法从S3读取PNG

时间:2018-08-16 09:59:54

标签: image go amazon-s3

我正在尝试从AWS S3读取png文件,该文件返回[]byte

但是,我无法从bytes.NewReader()中读取png。这是我的代码

config := aws.Config{
    Region: aws.String(region),
}
sess := session.Must(session.NewSession(&config))

svc := s3.New(sess)

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

if err != nil {
    return make([]byte, 0), err
}

buf := new(bytes.Buffer)
buf.ReadFrom(s3Output.Body)

imgReader := bytes.NewReader(buf.Bytes())
_, format, err := image.DecodeConfig(imgReader )
if err != nil {
    return nil, err
}
fmt.Println(format)
img, err := png.Decode(imgReader)
if err != nil {
    return nil, err
}

格式返回png,但返回错误png: invalid format: not a PNG file

我尝试使用文件,但成功

file, err := os.Open(ImageFile)
if err != nil {
    log.Fatal(err)
}

// decode jpeg into image.Image
img, err := png.Decode(file)
if err != nil {
    log.Fatal(err)
}
file.Close()

我该如何解决?

更新

这是s3Output

的输出
{
  AcceptRanges: "bytes",
  Body: buffer(0xc04220e040),
  ContentLength: 102104,
  ContentType: "image/png",
  ETag: "\"d1b5490e26ddd6259cd5d17fa3c4dc6b\"",
  LastModified: 2018-08-16 09:30:35 +0000 UTC,
  Metadata: {

  }
}

2 个答案:

答案 0 :(得分:1)

尝试使用AWS S3下载管理器,它将使您可以直接下载图像以及元数据和在aws s3上上传的图像的位置,

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

if err != nil {
    log.Printf("Could not download from S3: %v", err)
}

使用s3Output.Body将为您提供输出,因为它已经以字节为单位,并带有上载的文件内容。因此,您需要在将图像转换为字节后使用图像创建缓冲区。函数png.Decode在io.Reader上的工作方式为:

func Decode(r io.Reader) (image.Image, error)
  

Decode从r读取PNG图像,并将其作为image.Image返回。的   返回的图像类型取决于PNG内容。

检查this example,其中使用png.Decode将Base64代码转换为图像。

AWS S3提供了特殊的下载管理器来直接执行从存储桶中下载文件的操作。有关更多信息,Check AWS S3 Basic bucket operations

答案 1 :(得分:0)

我不知道为什么,但是如果我使用s3Output.Body而不是字节,则会得到正确的结果。

config := aws.Config{
    Region: aws.String(region),
}
sess := session.Must(session.NewSession(&config))

svc := s3.New(sess)

s3Output, err := svc.GetObject(&s3.GetObjectInput{
    Bucket: aws.String(bucket),
    Key:    aws.String(key),
})
img, err := png.Decode(s3Output.Body)

您可以解释为什么会发生这种情况,我很乐意将您的答案标记为正确答案:)

事实证明,读者会在image.DecodeConfig中被改变

所以,如果我使用

imgFormat := bytes.NewReader(buf.Bytes())
imgReader := bytes.NewReader(buf.Bytes())
_, format, err := image.DecodeConfig(imgFormat)
if err != nil {
    return nil, err
}
fmt.Println(format)
img, err := png.Decode(imgReader)
if err != nil {
    return nil, err
}
fmt.Println(img)
return nil, nil

它不会抛出任何错误。我现在会坚持使用,但是如果有更好的方法,请随时发布答案。