我正在将文件上传到Amazon S3存储桶。文件正在上传,但我得到以下警告。
警告:没有为流数据指定内容长度。流内容 将被缓冲在内存中,并可能导致内存不足错误。
所以我在代码中添加了以下行
metaData.setContentLength(IOUtils.toByteArray(input).length);
然后我收到以下消息。我甚至都不知道这是警告还是什么。
数据读取的长度与预期的不同:dataLength = 0; expectedLength = 111992; includeSkipped = FALSE; in.getClass()=类 sun.net.httpserver.FixedLengthInputStream; markedSupported = FALSE; 标记= 0; resetSinceLastMarked = FALSE; markCount = 0; resetCount = 0
如何将contentLength设置为InputSteam的metaData?任何帮助将不胜感激。
答案 0 :(得分:23)
当您使用IOUtils.toByteArray
读取数据时,会消耗InputStream。当AWS API尝试读取它时,它的长度为零。
将内容读入字节数组并提供将该数组包装到API的InputStream:
byte[] bytes = IOUtils.toByteArray(input);
metaData.setContentLength(bytes.length);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, key, byteArrayInputStream, metadata);
client.putObject(putObjectRequest);
答案 1 :(得分:1)
请注意,通过使用ByteBuffer,您只需手动完成AWS SDK已经为您自动完成的工作!它仍然将整个流缓冲到内存中,并且与从SDK发出警告的原始解决方案一样好。
仅当您有另一种方法来了解流的长度时(例如,从文件创建流时),您才能摆脱内存问题:
void uploadFile(String bucketName, File file) {
try (final InputStream stream = new FileInputStream(file)) {
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(file.length());
s3client.putObject(
new PutObjectRequest(bucketName, file.getName(), stream, metadata)
);
}
}
答案 2 :(得分:0)
最新消息! AWS SDK 2.0具有对上传文件的内置支持:
s3client.putObject(
(builder) -> builder.bucket(myBucket).key(file.getName()),
RequestBody.fromFile(file)
);
还有RequestBody
个用于获取字符串或缓冲区的方法,这些方法可自动有效地设置Content-Length。仅当您拥有另一种InputStream时,您仍然需要自己提供长度-但是,在使用所有其他选项的情况下,这种情况现在应该很少见了。