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
fromInputStreammethod
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
InputStreamto a byte array usingIOUtils.toByteArray(inputStream)(or in Java 9 ,inputStream.readAllBytes()) and then usefromBytesdirectly - As above but then convert the
byte[]to aByteBufferusingByteBuffer.wrap(byteArray)and then usefromByteBuffer - Create a new
Fileobject specifying a filename, copy the contents of theInputStreamto the file'sFileOutputStreamusingIOUtils.copy(), and then usefromFile(File file) - As above but instead of providing the
Fileobject, provide its path tofromFile(Path path)after you've written to it'sFileOutputStream - Convert the
InputSteamto aPublisher<ByteArray>usingDataBufferUtils.readByteChannelfrom the Spring Framework, AkkaStreamConvertersetc. and then usefromPublisher - Convert the
InputStreamto a UTF-8 encodedStringthen usefromString(String string)(no need to specify theCharsetif it is UTF-8 encoded) - Convert the
InputStreamto a non-UTF-8 encodedStringthen 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));
}
