I am upgrading S3Client in aws cloud service to S3AsyncClient.
I have this function to convert to async:
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));
}
I have this function to convert to async:
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(???));
}
As you can see in second method above when I convert the first function above to async I need to use AsyncRequestBody instead of RequestBody. AsyncRequestBody doesn't have fromInputStream method but it have fromPublisher method that I want to use, the fromPublisher method get as parameter type of Publisher.
So my question is how to convert my inputStream into an Publisher?
CodePudding user response:
AsyncRequestBody doesn't have
fromInputStream
method
Correct however, it has a plethora of other ways to create an AsyncRequestBody
:
fromByteBuffer(ByteBuffer byteBuffer)
fromBytes(byte[] bytes)
fromFile(File file)
fromFile(Path path)
fromPublisher(org.reactivestreams.Publisher<ByteBuffer> publisher)
fromString(String string)
fromString(String string, Charset cs)
Considering the above, you have a few solutions:
- Convert the
InputStream
to a byte array usingIOUtils.toByteArray(inputStream)
(or in Java 9 ,inputStream.readAllBytes()
) and then usefromBytes
directly - As above but then convert the
byte[]
to aByteBuffer
usingByteBuffer.wrap(byteArray)
and then usefromByteBuffer
- Create a new
File
object specifying a filename, copy the contents of theInputStream
to the file'sFileOutputStream
usingIOUtils.copy()
, and then usefromFile(File file)
- As above but instead of providing the
File
object, provide its path tofromFile(Path path)
after you've written to it'sFileOutputStream
- Convert the
InputSteam
to aPublisher<ByteArray>
usingDataBufferUtils.readByteChannel
from the Spring Framework, AkkaStreamConverters
etc. and then usefromPublisher
- Convert the
InputStream
to a UTF-8 encodedString
then usefromString(String string)
(no need to specify theCharset
if it is UTF-8 encoded) - Convert the
InputStream
to a non-UTF-8 encodedString
then usefromString(String string, Charset cs)
, specifying theCharSet
Of course, some of the above are plain redundant in your case e.g. fromFile(Path path)
is for files that you've already stored & converting the InputSteam
to a Publisher<ByteArray>
is going to be a pain but I've included all possible solutions for completeness.
I would approach this using solution #1, resulting in the cleanest, simplest code out of the above.
Convert the InputStream
to byte[]
using inputStream.readAllBytes()
and then use AsyncRequestBody.fromBytes(...)
.
This should work:
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));
}