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