Home > Software engineering >  Uploading image to S3 bucket - No content length specified for stream data
Uploading image to S3 bucket - No content length specified for stream data

Time:09-17

I'm trying to upload an image to S3 Bucket using Spring boot, but I'm getting the following error: No content length specified for stream data. Stream contents will be buffered in memory and could result in out of memory errors.

FileStore.java

public void save(String path,
                 String fileName,
                 Optional<Map<String, String>> optionalMetadata,
                 InputStream inputStream) {
    ObjectMetadata metadata = new ObjectMetadata();

    optionalMetadata.ifPresent(map -> {
        if (!map.isEmpty()) {
            map.forEach(metadata::addUserMetadata);
        }
    });

    try {
        s3.putObject(path, fileName, inputStream, metadata);
    } catch (AmazonServiceException e) {
        throw new IllegalStateException("Failed to store file to s3", e);
    }
}

Service.java

//get file Metadata
    Map<String, String> metadata = extractMetadata(file);

    //upload to S3 bucket
    String path = String.format("%s/%s", BucketName.PROFILE_IMAGE.getBucketName(), id);

    try {
        filestore.save(path, "profileImage", Optional.of(metadata), file.getInputStream());
        player.setPlayerProfileImageLink(path   "/profileImage.jpg");
    } catch (IOException e) {
        throw new IllegalStateException(e);
    }

}

private Map<String, String> extractMetadata(MultipartFile file) {
    Map<String,String> metadata = new HashMap<>();
    metadata.put("Content-type", file.getContentType());
    metadata.put("Content-length",String.valueOf(file.getSize()));
    return metadata;
}

I've followed a tutorial to do this, and it worked fine for some time, but now I always get the same error and I don't know why.

CodePudding user response:

Changed the method to this and it worked:

public void uploadFile(String bucketName, String keyName, MultipartFile file) {
    try {
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentLength(file.getSize());
        s3.putObject(bucketName, keyName, file.getInputStream(), metadata);
    } catch (IOException ioe) {
        throw new IllegalStateException("IOException: "   ioe.getMessage());
    } catch (AmazonServiceException serviceException) {
        throw new IllegalStateException("AmazonServiceException: "  serviceException.getMessage());
    }

CodePudding user response:

The error clearly says that you are missing the Content-Length header from the request to put the object. If you want to put the object to S3 directly using InputStream, the Content-Length header becomes mandatory.

Actually, you are adding metadata like Content-Length to the user's metadata, which is incorrect. addUserMetadata method is meant to add user-specific metadata, like if you want to add tags to your S3 object.

From the documentation: addUserMetadata(String key, String value)

Adds the key-value pair of custom user-metadata for the associated object.

To set the Content-Length, use setContentLength(long contentLength) method instead.

Here is the link to the documentation which lists all the available methods for ObjectMetadata - https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/model/ObjectMetadata.html

  • Related