Conversation
Each of the six direct upload members (UploadAsync, UploadSinglePartAsync, UploadMultipartAsync, file path and stream forms) gains an overload taking an optional content type, following the shape InitiateMultipartUploadAsync already uses: the existing signature stays and delegates with a null type, so no compiled caller changes behavior. A null or blank value leaves the property unset and R2 applies its default; a non-blank value is applied verbatim and never inferred from the file extension, the bytes, or the object key. The single PUT path sets PutObjectRequest.ContentType; the multipart path records the type on the initiate request, the only place S3 reads the assembled object's Content-Type from. UploadAsync forwards the value down whichever branch its size check picks. The overloads that can take the single PUT path also accept an optional UploadChecksum. The digest is copied onto the PutObjectRequest property matching its algorithm (ChecksumCRC32, ChecksumCRC32C, ChecksumSHA1, ChecksumSHA256, MD5Digest) and R2 verifies the arriving bytes against it, failing the upload with 400 BadDigest and storing nothing on a mismatch (verified against live R2 for all five algorithms, 2026-08-25). Because the digest covers the whole object while a multipart upload is verified per part, UploadAsync throws ArgumentException when a checksum accompanies an input that would go multipart, before anything is sent; the multipart overloads take no checksum parameter. Unit tests cover the request each path sends (type set, blank left unset, pre-existing overloads unchanged, one digest property per algorithm) and both branches of both UploadAsync overloads. Integration tests verify the stored Content-Type via object metadata and pin BadDigest rejection on the direct upload path. The uploads article's threshold claim (5 GiB) is corrected to the actual 50 MiB. Version 2.4.0.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Each of the six direct upload members (UploadAsync, UploadSinglePartAsync, UploadMultipartAsync, file path and stream forms) gains an overload taking an optional content type, following the shape InitiateMultipartUploadAsync already uses: the existing signature stays and delegates with a null type, so no compiled caller changes behavior. A null or blank value leaves the property unset and R2 applies its default; a non-blank value is applied verbatim and never inferred from the file extension, the bytes, or the object key. The single PUT path sets PutObjectRequest.ContentType; the multipart path records the type on the initiate request, the only place S3 reads the assembled object's Content-Type from. UploadAsync forwards the value down whichever branch its size check picks.
The overloads that can take the single PUT path also accept an optional UploadChecksum. The digest is copied onto the PutObjectRequest property matching its algorithm (ChecksumCRC32, ChecksumCRC32C, ChecksumSHA1, ChecksumSHA256, MD5Digest) and R2 verifies the arriving bytes against it, failing the upload with 400 BadDigest and storing nothing on a mismatch (verified against live R2 for all five algorithms, 2026-08-25). Because the digest covers the whole object while a multipart upload is verified per part, UploadAsync throws ArgumentException when a checksum accompanies an input that would go multipart, before anything is sent; the multipart overloads take no checksum parameter.
Unit tests cover the request each path sends (type set, blank left unset, pre-existing overloads unchanged, one digest property per algorithm) and both branches of both UploadAsync overloads. Integration tests verify the stored Content-Type via object metadata and pin BadDigest rejection on the direct upload path. The uploads article's threshold claim (5 GiB) is corrected to the actual 50 MiB. Version 2.4.0.