Repository: minio/minio (language: go)

Issue:
List-part API call returns incorrect Size field for multi-part upload when compression is enabled
Hi team,

we're using Minio to store images pushed by Harbor (tried on MinIO 2024-03-30 and 2024-12-13)
When enabling compression on Minio for all new files (`mc admin config set s3 compression enable="on" extensions="" mime_types=""`), uploads by Harbor start failing.

## Expected Behavior
Uploads by Harbor should succeed whether compression is enabled or not on MinIO as this is a transparent feature

## Current Behavior
Uploads by Harbor fail when compression is enabled due to size mismatch between uploaded chunks size reported by Minio vs actual file size uploaded

Internally, Harbor seems to be using "distribution", which, when pushing multi-parts objects, compute the total size by listing uploaded parts :

https://github.com/distribution/distribution/blob/main/registry/storage/driver/s3-aws/s3.go#L1331
https://github.com/distribution/distribution/blob/main/registry/storage/driver/s3-aws/s3.go#L713

If the sum of all uploaded parts is different from the size of the uploaded file, Harbor fails.

We think that, in the list part call, MinIO reports the size of the actual part file on disk (`Size`, compressed) and not the size of the uncompressed part (`ActualSize`)

When listing uploaded parts, care is taken to fix the size reported for encrypted objects, but maybe not for the compressed ones ( we think it comes from here https://github.com/minio/minio/blob/16f8cf1c52f0a77eeb8f7565aaf7f7df12454583/cmd/object-multipart-handlers.go#L1188 )

According to AWS doc, the `Size` field contains the size of the uploaded data (https://docs.aws.amazon.com/AmazonS3/latest/API/API_Part.html)



## Steps to Reproduce (for bugs)

Reproducer (with aws-cli to permit using the list-parts call):

```
# Create a file with 2001 bytes
- python3 -c 'print("A" * 2000)' > part
# Enable compression on minio
- mc admin config set s3 compression enable="on" extensions=".testcompress" mime_types="application/testcompress"
# Create a multipart upload 
- UPLOAD_ID=$(aws --endpoint-url https://s3 s3api create-multipart-upload --bucket debug --key test.testcompress --content-type application/testcompress | jq -r .UploadId)
# Upload the 2001 bytes part
- aws --endpoint-url https://s3 s3api upload-part --bucket debug --key test.testcompress --part-number 1 --body part --upload-id "$UPLOAD_ID"
# List parts
- aws --endpoint-url https://s3 s3api list-parts --bucket debug --key test.testcompress --upload-id "$UPLOAD_ID"

```

When compression is enabled, reported size is 30:

```
{
    "Parts": [
        {
            "PartNumber": 1,
            "LastModified": "2024-12-19T10:50:46.776000+00:00",
            "ETag": "\"ba413841fb575b59013d38230c171473\"",
            "Size": 30
        }
    ],
    "ChecksumAlgorithm": "",
    "Initiator": {
        "ID": "02d6176db174dc93cb1b899f7c6078f08654445fe8cf1b6ce98d8855f66bdbf4",
        "DisplayName": "02d6176db174dc93cb1b899f7c6078f08654445fe8cf1b6ce98d8855f66bdbf4"
    },
    "Owner": {
        "DisplayName": "02d6176db174dc93cb1b899f7c6078f08654445fe8cf1b6ce98d8855f66bdbf4",
        "ID": "02d6176db174dc93cb1b899f7c6078f08654445fe8cf1b6ce98d8855f66bdbf4"
    },
    "StorageClass": "STANDARD"
}
```

When compression is disabled (disable compression, delete the "part" file and upload it again), reported size is the correct one (2001)

```
{
    "Parts": [
        {
            "PartNumber": 1,
            "LastModified": "2024-12-19T10:54:10.801000+00:00",
            "ETag": "\"ba413841fb575b59013d38230c171473\"",
            "Size": 2001
        }
    ],
    "ChecksumAlgorithm": "",
    "Initiator": {
        "ID": "02d6176db174dc93cb1b899f7c6078f08654445fe8cf1b6ce98d8855f66bdbf4",
        "DisplayName": "02d6176db174dc93cb1b899f7c6078f08654445fe8cf1b6ce98d8855f66bdbf4"
    },
    "Owner": {
        "DisplayName": "02d6176db174dc93cb1b899f7c6078f08654445fe8cf1b6ce98d8855f66bdbf4",
        "ID": "02d6176db174dc93cb1b899f7c6078f08654445fe8cf1b6ce98d8855f66bdbf4"
    },
    "StorageClass": "STANDARD"
}
```

## Your Environment
Tested on MinIO 2024-03-30 and 2024-12-13



Discussion / hints:

Fix patch:
diff --git a/cmd/object-multipart-handlers.go b/cmd/object-multipart-handlers.go
index d32ad30d42f5f..bd0c01684c279 100644
--- a/cmd/object-multipart-handlers.go
+++ b/cmd/object-multipart-handlers.go
@@ -1204,6 +1204,10 @@ func (api objectAPIHandlers) ListObjectPartsHandler(w http.ResponseWriter, r *ht
 			listPartsInfo.Parts[i].ETag = tryDecryptETag(objectEncryptionKey, p.ETag, kind == crypto.S3)
 			listPartsInfo.Parts[i].Size = p.ActualSize
 		}
+	} else if _, ok := listPartsInfo.UserDefined[ReservedMetadataPrefix+"compression"]; ok {
+		for i, p := range listPartsInfo.Parts {
+			listPartsInfo.Parts[i].Size = p.ActualSize
+		}
 	}
 
 	response := generateListPartsResponse(listPartsInfo, encodingType)


Test patch: