diff --git a/extensions/resteasy-reactive/rest-client-jaxrs/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java b/extensions/resteasy-reactive/rest-client-jaxrs/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java index 3816b652ac5534..9529ffff88426d 100644 --- a/extensions/resteasy-reactive/rest-client-jaxrs/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java +++ b/extensions/resteasy-reactive/rest-client-jaxrs/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java @@ -121,6 +121,7 @@ import org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames; import org.jboss.resteasy.reactive.common.processor.scanning.ResourceScanningResult; import org.jboss.resteasy.reactive.multipart.FileDownload; +import org.jboss.resteasy.reactive.multipart.FileUpload; import io.quarkus.arc.deployment.AdditionalBeanBuildItem; import io.quarkus.arc.deployment.BeanArchiveIndexBuildItem; @@ -190,6 +191,7 @@ public class JaxrsClientReactiveProcessor { private static final String PATH_SIGNATURE = "L" + java.nio.file.Path.class.getName().replace('.', '/') + ";"; private static final String BUFFER_SIGNATURE = "L" + Buffer.class.getName().replace('.', '/') + ";"; private static final String BYTE_ARRAY_SIGNATURE = "[B"; + private static final String FILE_UPLOAD_SIGNATURE = "L" + FileUpload.class.getName().replace('.', '/') + ";"; private static final Logger log = Logger.getLogger(JaxrsClientReactiveProcessor.class); @@ -1176,6 +1178,7 @@ private boolean isMultipartRequiringType(String signature, String partType) { || signature.equals(BUFFER_SIGNATURE) || signature.equals(BYTE_ARRAY_SIGNATURE) || signature.equals(MULTI_BYTE_SIGNATURE) + || signature.equals(FILE_UPLOAD_SIGNATURE) || partType != null); } @@ -1793,6 +1796,8 @@ private void handleMultipartField(String formParamName, String partType, String } else if (type.equals(Path.class.getName())) { // and so is path addFile(ifValueNotNull, multipartForm, formParamName, partType, partFilename, fieldValue); + } else if (type.equals(FileUpload.class.getName())) { + addFileUpload(fieldValue, multipartForm, methodCreator); } else if (type.equals(InputStream.class.getName())) { // and so is path addInputStream(ifValueNotNull, multipartForm, formParamName, partType, partFilename, fieldValue, type); @@ -1888,6 +1893,15 @@ private void addFile(BytecodeCreator methodCreator, AssignableResultHandle multi } } + private void addFileUpload(ResultHandle fieldValue, AssignableResultHandle multipartForm, + BytecodeCreator methodCreator) { + // MultipartForm#fileUpload(FileUpload fileUpload); + methodCreator.invokeVirtualMethod( + MethodDescriptor.ofMethod(ClientMultipartForm.class, "fileUpload", + ClientMultipartForm.class, FileUpload.class), + multipartForm, fieldValue); + } + private ResultHandle primitiveToString(BytecodeCreator methodCreator, ResultHandle fieldValue, FieldInfo field) { PrimitiveType primitiveType = field.type().asPrimitiveType(); switch (primitiveType.primitive()) { diff --git a/extensions/resteasy-reactive/rest-client/deployment/src/test/java/io/quarkus/rest/client/reactive/multipart/MultipartDetectionTest.java b/extensions/resteasy-reactive/rest-client/deployment/src/test/java/io/quarkus/rest/client/reactive/multipart/MultipartDetectionTest.java index ab0a0675b8de39..b3fd11d635c78f 100644 --- a/extensions/resteasy-reactive/rest-client/deployment/src/test/java/io/quarkus/rest/client/reactive/multipart/MultipartDetectionTest.java +++ b/extensions/resteasy-reactive/rest-client/deployment/src/test/java/io/quarkus/rest/client/reactive/multipart/MultipartDetectionTest.java @@ -81,6 +81,39 @@ void shouldCallImplicitEndpoints() throws IOException { .isEqualTo(file.getName() + " file Hello"); assertThat(client.postMultipartEntityImplicit(file.getName(), person)) .isEqualTo(file.getName() + " Stef:Epardaud"); + + assertThat(client.postMultipartImplicitFileUpload("Foo", new FileUpload() { + @Override + public String name() { + return "file"; + } + + @Override + public java.nio.file.Path filePath() { + return file.toPath(); + } + + @Override + public String fileName() { + return file.getName(); + } + + @Override + public long size() { + return -1; + } + + @Override + public String contentType() { + return "application/octet-stream"; + } + + @Override + public String charSet() { + return ""; + } + })) + .isEqualTo("Foo " + file.getName() + " Hello"); } @Path("form") @@ -142,6 +175,10 @@ String postMultipartEntityImplicit(@RestForm String name, @Consumes(MediaType.MULTIPART_FORM_DATA) String postMultipartExplicit(@RestForm String name, @RestForm File file); + @Path("multipart") + @POST + String postMultipartImplicitFileUpload(@RestForm String name, @RestForm FileUpload file); + @Path("urlencoded") @POST String postUrlencodedImplicit(@RestForm String name); diff --git a/extensions/resteasy-reactive/rest-client/deployment/src/test/java/io/quarkus/rest/client/reactive/multipart/MultipartFilenameTest.java b/extensions/resteasy-reactive/rest-client/deployment/src/test/java/io/quarkus/rest/client/reactive/multipart/MultipartFilenameTest.java index 2a70e77f31ff75..69bec01287d099 100644 --- a/extensions/resteasy-reactive/rest-client/deployment/src/test/java/io/quarkus/rest/client/reactive/multipart/MultipartFilenameTest.java +++ b/extensions/resteasy-reactive/rest-client/deployment/src/test/java/io/quarkus/rest/client/reactive/multipart/MultipartFilenameTest.java @@ -60,6 +60,49 @@ void shouldPassOriginalFileName() throws IOException { assertThat(client.postMultipart(form)).isEqualTo(file.getName()); } + @Test + void shouldWorkWithFileUpload() throws IOException { + Client client = RestClientBuilder.newBuilder().baseUri(baseUri).build(Client.class); + + File file = File.createTempFile("MultipartTest", ".txt"); + file.deleteOnExit(); + + ClientFormUsingFileUpload form = new ClientFormUsingFileUpload(); + form.file = new FileUpload() { + + @Override + public String name() { + return "myFile"; + } + + @Override + public java.nio.file.Path filePath() { + return file.toPath(); + } + + @Override + public String fileName() { + return file.getName(); + } + + @Override + public long size() { + return 0; + } + + @Override + public String contentType() { + return "application/octet-stream"; + } + + @Override + public String charSet() { + return ""; + } + }; + assertThat(client.postMultipartFileUpload(form)).isEqualTo(file.getName()); + } + @Test void shouldUseFileNameFromAnnotation() throws IOException { Client client = RestClientBuilder.newBuilder().baseUri(baseUri).build(Client.class); @@ -244,6 +287,10 @@ public interface Client { @Consumes(MediaType.MULTIPART_FORM_DATA) String postMultipart(@MultipartForm ClientForm clientForm); + @POST + @Consumes(MediaType.MULTIPART_FORM_DATA) + String postMultipartFileUpload(ClientFormUsingFileUpload clientForm); + @POST @Consumes(MediaType.MULTIPART_FORM_DATA) String postMultipartWithPartFilename(@MultipartForm ClientFormUsingFile clientForm); @@ -324,6 +371,11 @@ public static class ClientForm { public File file; } + public static class ClientFormUsingFileUpload { + @RestForm + public FileUpload file; + } + public static class ClientFormUsingFile { @FormParam("myFile") @PartType(APPLICATION_OCTET_STREAM) diff --git a/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/api/ClientMultipartForm.java b/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/api/ClientMultipartForm.java index 7b7bc74d9c2205..b2fcbb5852922e 100644 --- a/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/api/ClientMultipartForm.java +++ b/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/api/ClientMultipartForm.java @@ -7,6 +7,7 @@ import org.jboss.resteasy.reactive.client.impl.multipart.QuarkusMultipartForm; import org.jboss.resteasy.reactive.client.impl.multipart.QuarkusMultipartFormDataPart; +import org.jboss.resteasy.reactive.multipart.FileUpload; import io.smallrye.mutiny.Multi; import io.vertx.core.buffer.Buffer; @@ -86,4 +87,9 @@ public ClientMultipartForm multiAsTextFileUpload(String name, String filename, M return this; } + public ClientMultipartForm fileUpload(FileUpload fileUpload) { + binaryFileUpload(fileUpload.name(), fileUpload.fileName(), fileUpload.filePath().toString(), fileUpload.contentType()); + return this; + } + } diff --git a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/multipart/FileUpload.java b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/multipart/FileUpload.java index 57a2bc9996ffaf..b844cf4eab2504 100644 --- a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/multipart/FileUpload.java +++ b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/multipart/FileUpload.java @@ -5,7 +5,7 @@ /** * Represent a file that has been uploaded. *

- * WARNING: This type is currently only supported on the server + * This type is usually used on server, but it is also supported in the REST Client. */ public interface FileUpload extends FilePart {