Skip to content

Commit

Permalink
Merge pull request #19827 from michalszynkiewicz/multipart-file-name
Browse files Browse the repository at this point in the history
Set actual file name in Rest Client Reactive  multipart support
  • Loading branch information
michalszynkiewicz authored Sep 1, 2021
2 parents 465a4d1 + 55c8f01 commit dc7af63
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ public class JaxrsClientReactiveProcessor {
String.class, Object.class);
private static final MethodDescriptor MULTIVALUED_MAP_ADD = MethodDescriptor.ofMethod(MultivaluedMap.class, "add",
void.class, Object.class, Object.class);
private static final MethodDescriptor PATH_GET_FILENAME = MethodDescriptor.ofMethod(Path.class, "getFileName",
Path.class);
private static final MethodDescriptor OBJECT_TO_STRING = MethodDescriptor.ofMethod(Object.class, "toString", String.class);

static final DotName CONTINUATION = DotName.createSimple("kotlin.coroutines.Continuation");
private static final DotName UNI_KT = DotName.createSimple("io.smallrye.mutiny.coroutines.UniKt");
Expand Down Expand Up @@ -989,7 +992,7 @@ private ResultHandle createMultipartForm(MethodCreator methodCreator, ResultHand
formClass.name() + "." + field.name());
}
ResultHandle filePath = methodCreator.invokeVirtualMethod(
MethodDescriptor.ofMethod(File.class, "getPath", String.class), fieldValue);
MethodDescriptor.ofMethod(File.class, "toPath", Path.class), fieldValue);
addFile(methodCreator, multipartForm, formParamName, partType, filePath);
} else if (is(PATH, fieldClass, index)) {
// and so is path
Expand All @@ -998,9 +1001,7 @@ private ResultHandle createMultipartForm(MethodCreator methodCreator, ResultHand
"No @PartType annotation found on multipart form field of type Path: " +
formClass.name() + "." + field.name());
}
ResultHandle filePath = methodCreator.invokeInterfaceMethod(
MethodDescriptor.ofMethod(Path.class, "toString", String.class), fieldValue);
addFile(methodCreator, multipartForm, formParamName, partType, filePath);
addFile(methodCreator, multipartForm, formParamName, partType, fieldValue);
} else if (is(BUFFER, fieldClass, index)) {
// and buffer
addBuffer(methodCreator, multipartForm, formParamName, partType, fieldValue, field);
Expand Down Expand Up @@ -1047,6 +1048,9 @@ private ResultHandle createMultipartForm(MethodCreator methodCreator, ResultHand
*/
private void addFile(MethodCreator methodCreator, AssignableResultHandle multipartForm, String formParamName,
String partType, ResultHandle filePath) {
ResultHandle fileNamePath = methodCreator.invokeInterfaceMethod(PATH_GET_FILENAME, filePath);
ResultHandle fileName = methodCreator.invokeVirtualMethod(OBJECT_TO_STRING, fileNamePath);
ResultHandle pathString = methodCreator.invokeVirtualMethod(OBJECT_TO_STRING, filePath);
if (partType.equalsIgnoreCase(MediaType.APPLICATION_OCTET_STREAM)) {
methodCreator.assign(multipartForm,
// MultipartForm#binaryFileUpload(String name, String filename, String pathname, String mediaType);
Expand All @@ -1055,8 +1059,8 @@ private void addFile(MethodCreator methodCreator, AssignableResultHandle multipa
MethodDescriptor.ofMethod(MultipartForm.class, "binaryFileUpload",
MultipartForm.class, String.class, String.class, String.class,
String.class),
multipartForm, methodCreator.load(formParamName), methodCreator.load(formParamName),
filePath, methodCreator.load(partType)));
multipartForm, methodCreator.load(formParamName), fileName,
pathString, methodCreator.load(partType)));
} else {
methodCreator.assign(multipartForm,
// MultipartForm#textFileUpload(String name, String filename, String pathname, String mediaType);;
Expand All @@ -1065,8 +1069,8 @@ private void addFile(MethodCreator methodCreator, AssignableResultHandle multipa
MethodDescriptor.ofMethod(MultipartForm.class, "textFileUpload",
MultipartForm.class, String.class, String.class, String.class,
String.class),
multipartForm, methodCreator.load(formParamName), methodCreator.load(formParamName),
filePath, methodCreator.load(partType)));
multipartForm, methodCreator.load(formParamName), fileName,
pathString, methodCreator.load(partType)));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,8 @@ private MultipartPopulatorGenerator() {
*/
static String generate(ClassInfo multipartClassInfo, ClassOutput classOutput, IndexView index) {
if (!multipartClassInfo.hasNoArgsConstructor()) {
throw new IllegalArgumentException("Classes annotated with '@MultipartForm' must contain a no-args constructor");
throw new IllegalArgumentException("Classes annotated with '@MultipartForm' must contain a no-args constructor. " +
"The constructor is missing on " + multipartClassInfo.name());
}

String multipartClassName = multipartClassInfo.name().toString();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package io.quarkus.rest.client.reactive;

import static org.assertj.core.api.Assertions.assertThat;

import java.io.File;
import java.io.IOException;
import java.net.URI;

import javax.enterprise.context.ApplicationScoped;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;

import org.eclipse.microprofile.rest.client.RestClientBuilder;
import org.jboss.resteasy.reactive.MultipartForm;
import org.jboss.resteasy.reactive.PartType;
import org.jboss.resteasy.reactive.multipart.FileUpload;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.quarkus.test.common.http.TestHTTPResource;

public class MultipartFilenameTest {

@TestHTTPResource
URI baseUri;

@RegisterExtension
static final QuarkusUnitTest TEST = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(Resource.class, FormData.class, Client.class, ClientForm.class))
.withConfigurationResource("dependent-test-application.properties");

@Test
void shouldPassOriginalFileName() throws IOException {
Client client = RestClientBuilder.newBuilder().baseUri(baseUri).build(Client.class);

File file = File.createTempFile("MultipartTest", ".txt");
file.deleteOnExit();

ClientForm form = new ClientForm();
form.file = file;
assertThat(client.postMultipart(form)).isEqualTo(file.getName());
}

@Path("/multipart")
@ApplicationScoped
public static class Resource {
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
public String upload(@MultipartForm FormData form) {
return form.myFile.fileName();
}
}

public static class FormData {
@FormParam("myFile")
public FileUpload myFile;

}

@Path("/multipart")
public interface Client {
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
String postMultipart(@MultipartForm ClientForm clientForm);

}

public static class ClientForm {
@FormParam("myFile")
@PartType(MediaType.APPLICATION_OCTET_STREAM)
public File file;
}
}

0 comments on commit dc7af63

Please sign in to comment.