aws-sdk-java-v2 icon indicating copy to clipboard operation
aws-sdk-java-v2 copied to clipboard

MultipartS3AsyncClient infers content type for single-part uploads but not multi-part uploads

Open mikewatt opened this issue 1 month ago • 1 comments

Describe the bug

MultipartS3AsyncClient.putObject(r, body) will set the uploaded object's content type provided by body (if not explicitly provided as metadata) if the upload is performed as a single part upload, but not if the upload is performed as a multi part upload. This can be confusing as smaller uploaded objects have a content type set, and larger objects do not.

A similar scenario from 1.x: The SDK v1.x TransferManager class would fill in a missing content type for both single and multi part uploads.

Regression Issue

  • [ ] Select this option if this issue appears to be a regression.

Expected Behavior

Consistent content-type behavior (either set equivalently or not set at all) regardless of upload size.

Current Behavior

A file under the multi-part threshold will have content-type set based on the detected file type; a file over the multi-part threshold will not have content-type set.

Reproduction Steps

    public void test() {
      var s3Client =
          S3AsyncClient.builder()
              .multipartEnabled(true)
              .multipartConfiguration(c -> c.thresholdInBytes(8L * 1024 * 1024))
              .forcePathStyle(true)
              .build();

      // Single part upload
      s3Client
          .putObject(
              r -> r.bucket(BUCKET).key("object1"), AsyncRequestBody.fromFile(new File("/tmp/video_5MB.mp4")))
          .join();

      // Multi part upload
      s3Client
          .putObject(
              r -> r.bucket(BUCKET).key("object2"), AsyncRequestBody.fromFile(new File("/tmp/video_10MB.mp4")))
          .join();

      {
        // Succeeds
        var md = s3Client.headObject(r -> r.bucket(BUCKET).key("object1")).join();
        assertThat(md.contentType()).isEqualTo("video/mp4");
      }

      {
        // Fails
        var md = s3Client.headObject(r -> r.bucket(BUCKET).key("object2")).join();
        assertThat(md.contentType()).isEqualTo("video/mp4");
      }
    }

Possible Solution

Content type appears to be set for single part uploads here: https://github.com/aws/aws-sdk-java-v2/blob/2.38.7/core/sdk-core/src/main/java/software/amazon/awssdk/core/runtime/transform/AsyncStreamingRequestMarshaller.java#L49-L51

Additional Information/Context

No response

AWS Java SDK version used

2.38.7

JDK version used

openjdk version "17.0.16"

Operating System and version

macOS 26.1

mikewatt avatar Dec 03 '25 00:12 mikewatt

Hi @mikewatt

Thank you for reporting the issue. I agree this is a resonable ask to add automatic content-type detection for multipart uploads as it currently does for single-part uploads. I will review it with the team for further steps on it.

As you are likely already aware, you can work around this in the meantime by explicity setting the content-type for multipart uploads.

Regards, Chaitanya

bhoradc avatar Dec 03 '25 21:12 bhoradc