amazon-web-servicesgoaws-sdkaws-sdk-go

AWS S3 ListObjectsV2 returns "folder" as an object


I am trying to list all the files in an S3 bucket under a specific directory (I know that S3 does not really have directories.).

The structure is:

Bucket-Name:Folder1/Folder2/Folder3/file

So in the S3 world I believe this is just storing a file called the above.

Here is my code:

    params := &s3.ListObjectsV2Input{
        Bucket: aws.String(os.Getenv("S3_USER_BUCKET")),
        Prefix: aws.String(key + loc[0] + "/"),
    }

    resp, _ := svc.ListObjectsV2(params)

The resp contains the file I would expect, as well as the "directory" it is stored in:

  Contents: [{
      ETag: "\"TAG\"",
      Key: "Folder1/Folder2/Folder3/",
      LastModified: 2023-03-02 17:32:17 +0000 UTC,
      Size: 0,
      StorageClass: "STANDARD"
    },{
      ETag: "\"TAG\"",
      Key: "Folder1/Folder2/Folder3/file",
      LastModified: 2023-03-02 17:32:30 +0000 UTC,
      Size: 106808,
      StorageClass: "STANDARD"
    }],
  IsTruncated: false,
  KeyCount: 2,
  MaxKeys: 1000,
  Name: "BUCKET",
  Prefix: "Folder1/Folder2/Folder3/"
}

I have also tried:

    params := &s3.ListObjectsV2Input{
        Bucket: aws.String(os.Getenv("S3_USER_BUCKET")),
        Prefix: aws.String(key + loc[0] + "/"),
        Delimiter: aws.String("/"),
    }

    resp, _ := svc.ListObjectsV2(params)

But the result is the same.

Here is the result of params:

Params:  {
  Bucket: "BUCKET",
  Prefix: "Folder1/Folder2/Folder3/"
}


Solution

  • I assume you are asking why there is a directory returned as an object.

    You are quite correct that Amazon S3 does not use directories. Instead, the filename (Key) of an object is the full path, including the name of the file. Directories do not need to be created before an object is created an a particular path.

    However, if somebody clicks the Create folder button in the S3 management console, it will create a zero-length object with the name of the directory. This 'forces' the directory to appear (because there is an object in it), but it is actually a zero-length object.

    Looking at your listing result:

      Contents: [{
          ETag: "\"TAG\"",
          Key: "Folder1/Folder2/Folder3/",
          LastModified: 2023-03-02 17:32:17 +0000 UTC,
          Size: 0,
          StorageClass: "STANDARD"
    

    You will notice it says Size: 0, so this is the zero-length object.

    If you want to ignore these types of files in your listing, simply skip-over zero-length objects in your code.