最近我们决定迁移 Java 文件上传/下载用例,以通过 AWS S3 从我们的旧 SFTP VM 满足需求。我的文件大小通常在 0-10 MB 之间,并且可以有多个并发用户(Java API)上传文件。
这样做的时候,我遇到了 4 个选项,主要是将文件上传到 S3 存储桶。
RequestBody.fromBytes(IoUtils.toByteArray(s3FileObject.getInputStream()));
/// 这会消耗大量内存,因为它将整个流读入 byteArray,然后通过 putObject 写入 S3
RequestBody.fromInputStream(s3FileObject.getInputStream(), s3FileObject.getInputStream().available());
/// 这里我真的没有输入流的大小(因为 s3FileObject.getInputStream().available() 并不总是正确获取输入流的长度)
RequestBody.fromFile(file)
/// 我真的不想在我的 Java serevr 或临时文件夹上创建临时文件,因为与我们最初通过 SFTP 上传到 VM 的方法相比,这是开销很大。
s3.uploadPart(part,RequestBody.fromBytes(bytes)).eTag();
// 最小部分大小为 5 MB,因此多个用户说 100 个上传这些文件会消耗大量内存。
我之前是如何实施的 我们有 Apach VFS,它用于将输出流打开到 SFTP 文件,我们用于从输入流读取小块并写入 OutputStream(SFTP 中的文件)
示例代码
public long transferStream(InputStream inputStream, OutputStream outputStream) throws IOException
{
int bytesRead = 0;
long streamSize = 0;
byte[] buf = new byte[4 * 1024];
while ((bytesRead = inputStream.read(buf)) != -1)
{
streamSize += bytesRead;
outputStream.write(buf, 0, bytesRead);
outputStream.flush();
}
outputStream.flush();
return streamSize;
}
有没有更好的方法来处理 S3 上传而没有太多的内存开销和临时文件。
谢谢
Spring-Cloud-Aws现在在内存中提供了S3OutputStream,看看这个类可能会有帮助。 https://github.com/awspring/spring-cloud-aws/blob/main/spring-cloud-aws-s3-parent/spring-cloud-aws-s3/src/main/java/io/awspring/cloud /s3/InMemoryBufferingS3OutputStream.java