Documentation Index
Fetch the complete documentation index at: https://mintlify.com/deuxfleurs-org/garage/llms.txt
Use this file to discover all available pages before exploring further.
Multipart uploads allow you to upload large objects in parts, with better reliability and performance compared to single-request uploads.
Overview
The multipart upload process consists of three steps:
- Initiate - Create a new multipart upload and receive an upload ID
- Upload Parts - Upload object parts (1-10,000 parts, each 5MB-5GB)
- Complete - Combine all parts into a single object
Use multipart uploads for objects larger than 100MB. Parts can be uploaded in parallel for better performance.
CreateMultipartUpload
Initiates a multipart upload and returns an upload ID.
POST /{bucket}/{key}?uploads HTTP/1.1
Host: s3.garage.example.com
Accepts the same metadata headers as PutObject:
MIME type for the final object
Custom metadata for the object
Checksums
Checksum algorithm to use: CRC32, CRC32C, CRC64NVME, SHA1, or SHA256
Example
aws s3api create-multipart-upload --bucket my-bucket --key large-file.bin \
--endpoint-url https://s3.garage.example.com
curl -X POST "https://s3.garage.example.com/my-bucket/large-file.bin?uploads" \
-H "Authorization: AWS4-HMAC-SHA256 ..." \
-H "Content-Type: application/octet-stream"
Response
<?xml version="1.0" encoding="UTF-8"?>
<InitiateMultipartUploadResult>
<Bucket>my-bucket</Bucket>
<Key>large-file.bin</Key>
<UploadId>1a2b3c4d5e6f7g8h9i0j</UploadId>
</InitiateMultipartUploadResult>
Hex-encoded upload identifier (use this in subsequent requests)
UploadPart
Uploads a part of the object.
PUT /{bucket}/{key}?partNumber={part-number}&uploadId={upload-id} HTTP/1.1
Host: s3.garage.example.com
Content-Length: {part-size}
Query Parameters
Upload ID from CreateMultipartUpload
Size of this part in bytes (minimum 5MB except for the last part)
Base64-encoded MD5 hash of the part data
Checksums
If a checksum algorithm was specified in CreateMultipartUpload, include the part checksum:
Base64-encoded CRC32 checksum of this part
Base64-encoded CRC32C checksum of this part
Base64-encoded CRC64NVME checksum of this part
Base64-encoded SHA1 checksum of this part
Base64-encoded SHA256 checksum of this part
Example
aws s3api upload-part --bucket my-bucket --key large-file.bin \
--part-number 1 --upload-id "1a2b3c4d5e6f7g8h9i0j" \
--body part1.bin \
--endpoint-url https://s3.garage.example.com
curl -X PUT "https://s3.garage.example.com/my-bucket/large-file.bin?partNumber=1&uploadId=1a2b3c4d5e6f7g8h9i0j" \
-H "Authorization: AWS4-HMAC-SHA256 ..." \
-H "Content-Length: 10485760" \
--data-binary @part1.bin
Response
HTTP/1.1 200 OK
ETag: "d41d8cd98f00b204e9800998ecf8427e"
Save the ETag from each UploadPart response - you’ll need them to complete the upload.
UploadPartCopy
Copies data from an existing object as a part.
PUT /{bucket}/{key}?partNumber={part-number}&uploadId={upload-id} HTTP/1.1
Host: s3.garage.example.com
x-amz-copy-source: /source-bucket/source-key
Source object path: /bucket/key
Byte range to copy from source: bytes=0-10485759
Example
aws s3api upload-part-copy --bucket my-bucket --key large-file.bin \
--part-number 1 --upload-id "1a2b3c4d5e6f7g8h9i0j" \
--copy-source "/source-bucket/source-file.bin" \
--copy-source-range "bytes=0-10485759" \
--endpoint-url https://s3.garage.example.com
ListParts
Lists the parts that have been uploaded.
GET /{bucket}/{key}?uploadId={upload-id} HTTP/1.1
Host: s3.garage.example.com
Query Parameters
Upload ID from CreateMultipartUpload
Maximum number of parts to return (1-1000)
Part number to start listing from
Example
aws s3api list-parts --bucket my-bucket --key large-file.bin \
--upload-id "1a2b3c4d5e6f7g8h9i0j" \
--endpoint-url https://s3.garage.example.com
Response
<?xml version="1.0" encoding="UTF-8"?>
<ListPartsResult>
<Bucket>my-bucket</Bucket>
<Key>large-file.bin</Key>
<UploadId>1a2b3c4d5e6f7g8h9i0j</UploadId>
<PartNumberMarker>0</PartNumberMarker>
<NextPartNumberMarker>2</NextPartNumberMarker>
<MaxParts>1000</MaxParts>
<IsTruncated>false</IsTruncated>
<Part>
<PartNumber>1</PartNumber>
<ETag>"d41d8cd98f00b204e9800998ecf8427e"</ETag>
<Size>10485760</Size>
</Part>
<Part>
<PartNumber>2</PartNumber>
<ETag>"098f6bcd4621d373cade4e832627b4f6"</ETag>
<Size>5242880</Size>
</Part>
</ListPartsResult>
CompleteMultipartUpload
Completes the multipart upload by assembling previously uploaded parts.
POST /{bucket}/{key}?uploadId={upload-id} HTTP/1.1
Host: s3.garage.example.com
Content-Type: application/xml
Request Body
<?xml version="1.0" encoding="UTF-8"?>
<CompleteMultipartUpload>
<Part>
<PartNumber>1</PartNumber>
<ETag>"d41d8cd98f00b204e9800998ecf8427e"</ETag>
</Part>
<Part>
<PartNumber>2</PartNumber>
<ETag>"098f6bcd4621d373cade4e832627b4f6"</ETag>
</Part>
</CompleteMultipartUpload>
Part numbers must be in ascending order, but don’t need to be sequential (e.g., 1, 3, 5 is valid).
Expected CRC32 checksum of the complete object (composite checksum)
Expected CRC32C checksum of the complete object
Expected SHA1 checksum of the complete object
Expected SHA256 checksum of the complete object
Example
aws s3api complete-multipart-upload --bucket my-bucket --key large-file.bin \
--upload-id "1a2b3c4d5e6f7g8h9i0j" \
--multipart-upload "Parts=[{ETag='d41d8cd98f00b204e9800998ecf8427e',PartNumber=1},{ETag='098f6bcd4621d373cade4e832627b4f6',PartNumber=2}]" \
--endpoint-url https://s3.garage.example.com
Response
<?xml version="1.0" encoding="UTF-8"?>
<CompleteMultipartUploadResult>
<Location>https://my-bucket.s3.garage.example.com/large-file.bin</Location>
<Bucket>my-bucket</Bucket>
<Key>large-file.bin</Key>
<ETag>"abc123def456-2"</ETag>
</CompleteMultipartUploadResult>
The ETag for multipart uploads has the format {md5}-{part-count}, where the MD5 is calculated from the concatenated ETags of all parts.
AbortMultipartUpload
Aborts a multipart upload and frees storage used by uploaded parts.
DELETE /{bucket}/{key}?uploadId={upload-id} HTTP/1.1
Host: s3.garage.example.com
Example
aws s3api abort-multipart-upload --bucket my-bucket --key large-file.bin \
--upload-id "1a2b3c4d5e6f7g8h9i0j" \
--endpoint-url https://s3.garage.example.com
curl -X DELETE "https://s3.garage.example.com/my-bucket/large-file.bin?uploadId=1a2b3c4d5e6f7g8h9i0j" \
-H "Authorization: AWS4-HMAC-SHA256 ..."
Response
ListMultipartUploads
Lists in-progress multipart uploads for a bucket.
GET /{bucket}?uploads HTTP/1.1
Host: s3.garage.example.com
Query Parameters
Encoding for keys in response: url
Key to start listing from
Maximum uploads to return (1-1000)
Limit to uploads for keys with this prefix
Upload ID to start from (for pagination)
Example
aws s3api list-multipart-uploads --bucket my-bucket \
--endpoint-url https://s3.garage.example.com
Response
<?xml version="1.0" encoding="UTF-8"?>
<ListMultipartUploadsResult>
<Bucket>my-bucket</Bucket>
<KeyMarker/>
<UploadIdMarker/>
<MaxUploads>1000</MaxUploads>
<IsTruncated>false</IsTruncated>
<Upload>
<Key>large-file.bin</Key>
<UploadId>1a2b3c4d5e6f7g8h9i0j</UploadId>
<Initiated>2026-03-04T10:30:00.000Z</Initiated>
</Upload>
</ListMultipartUploadsResult>
Checksum Types
When using checksums with multipart uploads, Garage supports two checksum types:
Composite Checksums
Calculated by hashing the concatenation of individual part checksums. Supported for:
Full-Object Checksums
Calculated by combining part CRCs using CRC concatenation properties. Supported for:
Specify the checksum type in the CompleteMultipartUpload request:
x-amz-checksum-type: COMPOSITE
or
x-amz-checksum-type: FULL_OBJECT
Best Practices
- Use parts of at least 10-100 MB for optimal performance
- All parts except the last must be at least 5 MB
- Maximum part size is 5 GB
- Maximum 10,000 parts per upload
Upload parts in parallel to maximize throughput:# Upload 4 parts in parallel
for i in {1..4}; do
aws s3api upload-part \
--bucket my-bucket \
--key large-file.bin \
--part-number $i \
--upload-id "1a2b3c4d5e6f7g8h9i0j" \
--body part${i}.bin \
--endpoint-url https://s3.garage.example.com &
done
wait
- Always call AbortMultipartUpload if an error occurs
- Use ListParts to verify uploaded parts before completing
- Set up lifecycle rules to automatically abort incomplete uploads after a timeout
- Use checksums for data integrity verification
- Choose CRC variants for better performance
- Use SHA variants when cryptographic strength is needed
Complete Example
Here’s a complete workflow using the AWS CLI:
# 1. Initiate upload
UPLOAD_ID=$(aws s3api create-multipart-upload \
--bucket my-bucket \
--key large-file.bin \
--endpoint-url https://s3.garage.example.com \
--output text --query 'UploadId')
# 2. Upload parts (example: 2 parts)
ETAG1=$(aws s3api upload-part \
--bucket my-bucket \
--key large-file.bin \
--part-number 1 \
--upload-id "$UPLOAD_ID" \
--body part1.bin \
--endpoint-url https://s3.garage.example.com \
--output text --query 'ETag')
ETAG2=$(aws s3api upload-part \
--bucket my-bucket \
--key large-file.bin \
--part-number 2 \
--upload-id "$UPLOAD_ID" \
--body part2.bin \
--endpoint-url https://s3.garage.example.com \
--output text --query 'ETag')
# 3. Complete the upload
aws s3api complete-multipart-upload \
--bucket my-bucket \
--key large-file.bin \
--upload-id "$UPLOAD_ID" \
--multipart-upload "Parts=[{ETag=$ETAG1,PartNumber=1},{ETag=$ETAG2,PartNumber=2}]" \
--endpoint-url https://s3.garage.example.com
See Also