'Why io.TeeReader provide nil object value? [closed]

I'm trying to run next chunk of go code to make a unique file name based on its hash and upload file to aws s3 bucket:

func PutImageToStore(f *bytes.Buffer) error {   
    hasher := md5.New()
    io.TeeReader(f, hasher)
    m5 := hex.EncodeToString(hasher.Sum(nil))
    uploader := manager.NewUploader(awsS3Client)
    // put object to storage:
    result, err := uploader.Upload(context.TODO(), &s3.PutObjectInput{
            Bucket: &myS3bucket,
        Key:    &m5,
        Body:   f,
    })
    return err
}

where awsS3client and myS3bucket are defined globally and f is an upload object, i.e earlier:

file, _, _  := r.FormFile("myimage")
io.Copy(f, file)

As a result of

PutImageToStore(f) 

I always get Key value (i.e. &m5) equal "d41d8cd98f00b204e9800998ecf8427e" which as I understand is a hash of nil.

The aws s3 upload is correct, the only issue is with the uploaded object name.

When I change the line

io.TeeReader(f, hasher)

to

io.Copy(hasher, f)

I get correct object name, but the object itself get corrupted and has 0 (zero) bytes.

So why I always get such a narrowed result for an object name? What is a difference among io.Copy() and io.TeeReader in this case?

I looked at this example (What is the difference between io.TeeRearder and io.Copy?), but still do not understand my case.

go


Solution 1:[1]

You need to capture the io.Reader returned by io.TeeReader:

r := io.TeeReader(f, hasher)

then when you read all of r's content, it will get written also to the hasher, so:

body, err := io.ReadAll(r)

and body will contain all the bytes of the file.


You can achieve the same without an io.TeeReader since you need the whole body anyway:

body, err := io.ReadAll(f) // check err

_, err = io.Copy(hasher, bytes Newsreader(body)) // check err

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1