Search code examples
amazon-web-servicesgoamazon-s3lambdaaws-lambda-go

Go lambda S3 file upload results in new object with size of 0


I'm writing my first golang api with aws lambda. The idea being to be able to record audio from a browser and save as an object in s3. I've gotten to the point of being able to save an object in the desired location in the s3 bucket, but the file is always size 0 / 0 kbs. But when I create a file and write to it, it has size.

Here's my go code:

func Handler(ctx context.Context, event PutAudiosEvent) (string, error) {
    decoded, err := base64.StdEncoding.DecodeString(event.FileContents)
    if err != nil {
        fmt.Println("Error decoding string")
        return "", err
    }
    //fmt.Println("Decoded is:", decoded)

    f, err := os.Create("/tmp/" + event.FileName)
    if err != nil {
        fmt.Println("Error creating file")
        return "", err
    }
    defer f.Close()

    numBytes, err := f.Write(decoded)
    fmt.Println("Num bytes:", numBytes)
    if err != nil {
        fmt.Println("Error writing")
        return "", err
    }

    if err = f.Sync(); err != nil {
        fmt.Println("Error syncing")
        return "", err
    }

    fileInfo, err := f.Stat()
    fmt.Println("Size:", fileInfo.Size())
    fmt.Println("Name:", fileInfo.Name())
    fmt.Println("Is dir:", fileInfo.IsDir())
    fmt.Println("Mode:", fileInfo.Mode())
    fmt.Println("Modtime", fileInfo.ModTime())
    fmt.Println("fileSys:", fileInfo.Sys())

    fmt.Println(event.UserName + "/" + event.Course + "/" + event.FileName)
    resp, err := s3Uploader.Upload(&s3manager.UploadInput{
        Bucket: aws.String(BUCKET_NAME),
        Key: aws.String(event.UserName + "/" + event.Course + "/" + event.Type + "/" + event.FileName),
        Body: f,
        ContentType: aws.String("audio/mpeg"),
    })

    if err != nil {
        fmt.Println("Error uploading", err)
        fmt.Println("Resp is:", resp)
        return "Error2", nil
    }

    return "File named '" + event.FileName + "' successfully uploaded", nil
}

Here's some of the output from cloudwatch: enter image description here

And here's the empty object:

enter image description here

So what am I doing wrong?


Solution

  • You have just created and written to the file f, and then you're using it as the upload Body. What happens is that the current position in the file is in the very end — this means that there are 0 bytes to read.

    You need to Seek to the beginning of the file, so that there's data to be read.

    Either way, for this use case it's unnecessary to write the file to storage prior to the upload — you can just upload it directly to S3 using the in-memory representation you already have in decoded.