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

3

我正在将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));
}

我有这个将函数转换为异步的功能:

我有这个将函数转换为异步的功能:

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(???));
}
    

如您在上述第二种方法中所见,当我将上述第一种函数转换为async时,我需要使用AsyncRequestBody而不是RequestBody。AsyncRequestBody没有fromInputStream方法,但它有一个我想要使用的fromPublisher方法,该方法以Publisher类型作为参数。

我的问题是如何将我的inputStream转换为Publisher?


考虑使用 fromFile() 替代:https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/AsyncRequestBody.html#fromFile-java.io.File- - Artem Bilan
1个回答

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. 使用IOUtils.toByteArray(inputStream)InputStream转换为字节数组(或者在Java 9+中使用inputStream.readAllBytes()),然后直接使用fromBytes
  2. 如上所述,但是使用ByteBuffer.wrap(byteArray)byte[]转换为ByteBuffer,然后使用fromByteBuffer
  3. 创建一个新的File对象指定文件名,使用IOUtils.copy()InputStream的内容复制到文件的FileOutputStream中,然后使用fromFile(File file)
  4. 如上所述,但不是提供File对象,而是在写入其FileOutputStream后将路径提供给fromFile(Path path)
  5. 使用Spring Framework的DataBufferUtils.readByteChannel、Akka的StreamConverters等将InputSteam转换为Publisher<ByteArray>,然后使用fromPublisher
  6. InputStream转换为UTF-8编码的String,然后使用fromString(String string)(如果是UTF-8编码,则无需指定Charset)。
  7. InputStream转换为非UTF-8编码的String,然后使用fromString(String string, Charset cs),指定CharSet
当然,有些方法在您的情况下是多余的,例如fromFile(Path path)适用于您已经存储的文件,将InputSteam转换为Publisher<ByteArray>会很麻烦,但为了完整性,我已包含所有可能的解决方案。
我会使用解决方案#1来处理,这样可以得到最干净、最简单的代码。 使用inputStream.readAllBytes()InputStream转换为byte[],然后使用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));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接