0

My go application can upload and remove objects from a Minio server on the same docker network but statObject and getObject return empty information. The file does exist in the minio console.

Here is my code.

func downloadFromMinio(rs *appResource, name string, userId float64) (multipart.File, error) {

    var file multipart.File

    user, err := getUser(rs, int64(userId))

    if err != nil {
        log.Println(err)
        return file, err
    }

    clientIdString := strconv.FormatInt(*user.CompanyId, 10)

    bucketName := "company-" + clientIdString

    log.Println(bucketName)

    log.Println(name)

    found, err := rs.mc.BucketExists(context.Background(), bucketName)
    if err != nil {
        log.Println("Error checking if minio bucket exists")
        log.Println(err)
        return file, err
    }
    if found {
        log.Println("Bucket found")
    }

    objInfo, err := rs.mc.StatObject(context.Background(), bucketName, name, minio.StatObjectOptions{})
    if err != nil {
        log.Println("Error checking minio object metadata")
        log.Println(err)
        return file, err
    } else {
        log.Println(objInfo)
    }

    downloadInfo, err := rs.mc.GetObject(context.Background(), bucketName, name, minio.GetObjectOptions{})

    if err != nil {
        log.Println("Error downloading minio object")
        log.Println(err)
        return file, err
    }

    log.Println("Successfully downloaded minio bytes: ", downloadInfo)

    return file, err
}

Here is the console output

2022/09/10 15:57:39 company-2
2022/09/10 15:57:39 cce2gmsabmis73dfo400
2022/09/10 15:57:39 Bucket found
2022/09/10 15:57:39 {dcd806b9b10e200a826066d5d5a1ab53 cce2gmsabmis73dfo400 2022-09-10 06:02:04 +0000 UTC 497741 application/octet-stream 0001-01-01 00:00:00 +0000 UTC map[Content-Type:[application/octet-stream]] map[] map[] 0 {{ }  } []  false false   0001-01-01 00:00:00 +0000 UTC  <nil> <nil>}
2022/09/10 15:57:39 Successfully downloaded minio bytes:  &{0xc0002f2f60 0xc000077620 0xc000077680 0xc0000776e0 0 {  {0 0 <nil>} 0  {0 0 <nil>} map[] map[] map[] 0 {{ }  } []  false false   {0 0 <nil>}  <nil> <nil>} false false false <nil> false false}

Here is the output from uploading the file again. I would expect to see non blank data in the equivalent download info and I would expect if file == nil in the calling function to be false instead of true as it is. Without this test I get a slice out of range error, indicating a nil file..

Successfully uploaded bytes:  {company-2 ccevamsabmis738hp8e0 dcd806b9b10e200a826066d5d5a1ab53 497741 0001-01-01 00:00:00 +0000 UTC   0001-01-01 00:00:00 +0000 UTC }
markhorrocks
  • 1,199
  • 19
  • 82
  • 151

1 Answers1

2

Well, the MinIO client is asynchronous under the hood, which means that an actual query to MinIO (or other S3 storage) happens only on trying to read from the object returned by GetObject().

Abstract from api-get-object.go:

// Read reads up to len(b) bytes into b. It returns the number of
// bytes read (0 <= n <= len(b)) and any error encountered. Returns
// io.EOF upon end of file.
func (o *Object) Read(b []byte) (n int, err error) {
    // ...

    // Send and receive from the first request.
    response, err := o.doGetRequest(readReq)
    if err != nil && err != io.EOF {
        // Save the error for future calls.
        o.prevErr = err
        return response.Size, err
    }

    // ...
}

You should do something like this:

import (
    "io"
    // other imports...
)

downloadInfo, err := rs.mc.GetObject(context.Background(), bucketName, name, minio.GetObjectOptions{})
if err != nil {
    // handle this error somehow
}

// The actual query to MinIO happens here.
downloadInfoBytes, err := io.ReadAll(downloadInfo)
if err != nil {
    // Handle this error.
    //
    // Possibly, this error will be of the "minio.ErrorResponse" type. Check its fields to understand what is an actual problem. 
}
Voldemar
  • 21
  • 3