0

我正在尝试使用 Spring boot 将图像上传到 S3 Bucket,但出现以下错误:没有为流数据指定内容长度。流内容将在内存中缓冲,并可能导致内存不足错误。

文件存储.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);
    }
}

服务.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;
}

我已经按照教程执行此操作,并且它工作了一段时间,但现在我总是遇到同样的错误,我不知道为什么。

4

2 回答 2

1

将方法更改为此并且它有效:

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());
    }
于 2021-09-17T08:01:32.293 回答
0

该错误清楚地表明您缺少Content-Length放置对象的请求中的标头。如果您想直接使用 将对象放到 S3 中InputStream,则Content-Length标头成为必需的。

实际上,您正在将元数据添加Content-Length到用户的元数据中,这是不正确的。addUserMetadata方法旨在添加特定于用户的元数据,例如,如果您想向 S3 对象添加标签。

从文档中: addUserMetadata(String key, String value)

为关联对象添加自定义用户元数据的键值对。

要设置Content-Length,请改用setContentLength(long contentLength)方法。

这是列出所有可用方法的文档的链接ObjectMetadata- https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/model/ObjectMetadata.html

于 2021-09-15T17:53:50.117 回答