我想使用 commons-fileupload 库的 Streaming API 将文件上传到 S3 存储桶。该代码用于解析请求
FileItemIterator iterStream = upload.getItemIterator(request);
while (iterStream.hasNext()) {
FileItemStream item = iterStream.next();
String name = item.getFieldName();
InputStream stream = item.openStream();
if (!item.isFormField()) {
// Process the InputStream stream (*)
} else {
String formFieldValue = Streams.asString(stream);
}
}
Run Code Online (Sandbox Code Playgroud)
这个用于初始化 S3 客户端和传输管理器
s3Client = AmazonS3ClientBuilder.standard()
.withRegion(Regions.DEFAULT_REGION)
.withCredentials(new ProfileCredentialsProvider())
.build();
transferManager = TransferManagerBuilder.standard()
.withS3Client(s3Client)
.build();
Run Code Online (Sandbox Code Playgroud)
我用了100MB的文件来测试。一开始,我的 springboot 应用程序启动时使用了大约 95MB 的内存。当使用该流(*)上传到 s3 存储桶时,使用
Upload upload = transferManager.upload(bucketName, key, inputStream, metadata );
Run Code Online (Sandbox Code Playgroud)
与将流 (*) 复制到 OutputStream,然后上传从该输出流创建的文件(从 90MB-> 100MB)相比,内存消耗明显更多(从 90MB->370MB)
try (
OutputStream out = new FileOutputStream(fileName);
) {
IOUtils.copy(inputStream, out);
}
PutObjectRequest request = new PutObjectRequest(
existingBucketName, fileName, new File(fileName));
Upload upload = transferManager.upload(request);
Run Code Online (Sandbox Code Playgroud)
我想知道为什么会这样。inputStream发生了什么导致直接上传消耗更多内存?非常感谢
如果您不知道文件的大小,只需使用文件上传即可。应避免使用InputStream 上传。参考这个,
从流上传选项时,调用者必须通过 ObjectMetadata 参数中的内容长度字段提供流中选项的大小。如果没有为输入流指定内容长度,则 TransferManager 将尝试在内存中缓冲所有流内容,并以传统的单部分上传方式上传选项。由于整个流内容必须缓冲在内存中,因此这可能非常昂贵,应尽可能避免。