升级S3Client到S3AsyncClient如何获取Publisher<ByteBuffer>?

Mic*_*ael 3 java stream amazon-s3 publisher reactor

我正在将 aws 云服务中的 S3Client 升级到 S3AsyncClient。

我有这个函数可以转换为异步:

public PutObjectResponse uploadFileByUrl(String fileUrl, String builderId, PbModel category, String categoryId)

    URL url = new URL(fileUrl);
    String[] fileNameArray = url.getFile().split("\\.");
    var uniqueFileName = prepareFileName(fileNameArray[fileNameArray.length -1]);

    URLConnection connection = url.openConnection();

    long contentSize = connection.getContentLengthLong();
    InputStream inputStream = connection.getInputStream();

    return s3Client.putObject(myObjectRequestBuild, RequestBody.fromInputStream(inputStream, contentSize));
}
Run Code Online (Sandbox Code Playgroud)

我有这个函数可以转换为异步:

public CompletableFuture<PutObjectResponse> uploadFileByUrl(String fileUrl, String builderId, PbModel category, String categoryId)

    URL url = new URL(fileUrl);
    String[] fileNameArray = url.getFile().split("\\.");
    var uniqueFileName = prepareFileName(fileNameArray[fileNameArray.length -1]);

    URLConnection connection = url.openConnection();

    long contentSize = connection.getContentLengthLong();
    InputStream inputStream = connection.getInputStream();

    return asyncClient.putObject(myObjectRequestBuild, AsyncRequestBody.fromPublisher(???));
}
    
Run Code Online (Sandbox Code Playgroud)

正如您在上面的第二种方法中看到的,当我将上面的第一个函数转换为异步函数时,我需要使用 AsyncRequestBody 而不是 RequestBody。AsyncRequestBody 没有 fromInputStream 方法,但它有我想使用的 fromPublisher 方法,fromPublisher 方法作为 Publisher 的参数类型获取。

所以我的问题是如何将我的 inputStream 转换为发布者?

Erm*_*ary 7

AsyncRequestBody 没有fromInputStream方法

然而,正确的是,它有很多其他方法来创建AsyncRequestBody

  1. fromByteBuffer(ByteBuffer byteBuffer)
  2. fromBytes(byte[] bytes)
  3. fromFile(File file)
  4. fromFile(Path path)
  5. fromPublisher(org.reactivestreams.Publisher<ByteBuffer> publisher)
  6. fromString(String string)
  7. fromString(String string, Charset cs)

考虑到上述情况,您有几个解决方案:

  1. 使用(或在 Java 9+ 中, )将 转换InputStream为字节数组,然后直接使用IOUtils.toByteArray(inputStream)inputStream.readAllBytes()fromBytes
  2. 如上所述,但然后将 转换byte[]ByteBufferusing ByteBuffer.wrap(byteArray),然后使用fromByteBuffer
  3. 创建一个File指定文件名的新对象,将 的内容复制InputStream到文件的FileOutputStreamusing IOUtils.copy(),然后使用fromFile(File file)
  4. 如上所述,但不是提供对象,而是在写入后File提供其路径fromFile(Path path)FileOutputStream
  5. 将 Spring Framework、Akka等转换InputSteamPublisher<ByteArray>using ,然后使用DataBufferUtils.readByteChannelStreamConvertersfromPublisher
  6. 转换InputStream为UTF-8编码String后使用(如果是UTF-8编码则fromString(String string)无需指定)Charset
  7. 将 转换InputStream为非 UTF-8 编码,String然后使用fromString(String string, Charset cs),指定CharSet

当然,上面的一些内容在您的情况下是完全多余的,例如fromFile(Path path)对于您已经存储的文件,将其转换InputSteam为 aPublisher<ByteArray>将会很痛苦,但为了完整性,我已经包含了所有可能的解决方案。


我将使用解决方案 #1 来解决这个问题,从而产生上述最干净、最简单的代码。

将 转换InputStreambyte[]using inputStream.readAllBytes(),然后使用AsyncRequestBody.fromBytes(...)

这应该有效:

public CompletableFuture<PutObjectResponse> uploadFileByUrl(String fileUrl, String builderId, PbModel category, String categoryId)
    URL url = new URL(fileUrl);
    String[] fileNameArray = url.getFile().split("\\.");
    var uniqueFileName = prepareFileName(fileNameArray[fileNameArray.length -1]);

    URLConnection connection = url.openConnection();

    long contentSize = connection.getContentLengthLong();
    InputStream inputStream = connection.getInputStream();

    byte[] fileByteArray = inputStream.readAllBytes();

    return asyncClient.putObject(myObjectRequestBuild, AsyncRequestBody.fromBytes(fileByteArray));
}
Run Code Online (Sandbox Code Playgroud)