fix: Added support for multiple files in multipart REST (#8986)
* fix: Added support for multiple files in multipart REST * Added test case * Review comment * Review comment
This commit is contained in:
parent
f17ce968e7
commit
ec34ef9a91
|
|
@ -26,6 +26,8 @@ import java.io.ByteArrayInputStream;
|
|||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
|
@ -150,26 +152,15 @@ public class DataUtils {
|
|||
if (MultipartFormDataType.TEXT.equals(multipartFormDataType)) {
|
||||
bodyBuilder.part(key, property.getValue());
|
||||
} else if (MultipartFormDataType.FILE.equals(multipartFormDataType)) {
|
||||
|
||||
MultipartFormDataDTO multipartFormDataDTO = null;
|
||||
try {
|
||||
multipartFormDataDTO = objectMapper.readValue(
|
||||
String.valueOf(property.getValue()),
|
||||
MultipartFormDataDTO.class);
|
||||
populateFileTypeBodyBuilder(bodyBuilder, property, outputMessage);
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
throw new AppsmithPluginException(
|
||||
AppsmithPluginError.PLUGIN_DATASOURCE_ARGUMENT_ERROR,
|
||||
"Unable to parse content. Expected to receive an array or object of multipart data"
|
||||
);
|
||||
}
|
||||
final MultipartFormDataDTO finalMultipartFormDataDTO = multipartFormDataDTO;
|
||||
Flux<DataBuffer> data = DataBufferUtils.readInputStream(
|
||||
() -> new ByteArrayInputStream(String
|
||||
.valueOf(finalMultipartFormDataDTO.getData())
|
||||
.getBytes(StandardCharsets.UTF_8)),
|
||||
outputMessage.bufferFactory(),
|
||||
4096);
|
||||
|
||||
bodyBuilder.asyncPart(key, data, DataBuffer.class)
|
||||
.filename(multipartFormDataDTO.getName())
|
||||
.contentType(MediaType.valueOf(multipartFormDataDTO.getType()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -181,6 +172,38 @@ public class DataUtils {
|
|||
});
|
||||
}
|
||||
|
||||
private void populateFileTypeBodyBuilder(MultipartBodyBuilder bodyBuilder, Property property, ClientHttpRequest outputMessage)
|
||||
throws JsonProcessingException {
|
||||
final Object fileValue = property.getValue();
|
||||
final String key = property.getKey();
|
||||
List<MultipartFormDataDTO> multipartFormDataDTOs = new ArrayList<>();
|
||||
try {
|
||||
multipartFormDataDTOs = Arrays.asList(
|
||||
objectMapper.readValue(
|
||||
String.valueOf(fileValue),
|
||||
MultipartFormDataDTO[].class));
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
final MultipartFormDataDTO multipartFormDataDTO = objectMapper.readValue(String.valueOf(fileValue),
|
||||
MultipartFormDataDTO.class);
|
||||
multipartFormDataDTOs.add(multipartFormDataDTO);
|
||||
}
|
||||
multipartFormDataDTOs.forEach(multipartFormDataDTO -> {
|
||||
final MultipartFormDataDTO finalMultipartFormDataDTO = multipartFormDataDTO;
|
||||
Flux<DataBuffer> data = DataBufferUtils.readInputStream(
|
||||
() -> new ByteArrayInputStream(String
|
||||
.valueOf(finalMultipartFormDataDTO.getData())
|
||||
.getBytes(StandardCharsets.UTF_8)),
|
||||
outputMessage.bufferFactory(),
|
||||
4096);
|
||||
|
||||
bodyBuilder.asyncPart(key, data, DataBuffer.class)
|
||||
.filename(multipartFormDataDTO.getName())
|
||||
.contentType(MediaType.valueOf(multipartFormDataDTO.getType()));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a JSON string, we infer the top-level type of the object it represents and then parse it into that
|
||||
* type. However, only `Map` and `List` top-levels are supported. Note that the map or list may contain
|
||||
|
|
|
|||
|
|
@ -163,6 +163,41 @@ public class DataUtilsTest {
|
|||
.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseMultipartFileData_withValidMultipleFileList_returnsExpectedBody() {
|
||||
List<Property> properties = new ArrayList<>();
|
||||
final Property p1 = new Property("fileType", "[{\"name\": \"test1.json\", \"type\": \"application/json\", \"data\" : {}}, {\"name\": \"test2.json\", \"type\": \"application/json\", \"data\" : {}}]");
|
||||
p1.setType("file");
|
||||
properties.add(p1);
|
||||
|
||||
final BodyInserter<Object, MockClientHttpRequest> bodyInserter =
|
||||
(BodyInserter<Object, MockClientHttpRequest>) dataUtils.parseMultipartFileData(properties);
|
||||
MockClientHttpRequest request = new MockClientHttpRequest(HttpMethod.POST, URI.create("https://example.com"));
|
||||
|
||||
Mono<Void> result = bodyInserter.insert(request, this.context);
|
||||
StepVerifier.create(result).expectComplete().verify();
|
||||
StepVerifier.create(DataBufferUtils.join(request.getBody()))
|
||||
.consumeNextWith(dataBuffer -> {
|
||||
byte[] resultBytes = new byte[dataBuffer.readableByteCount()];
|
||||
dataBuffer.read(resultBytes);
|
||||
DataBufferUtils.release(dataBuffer);
|
||||
String content = new String(resultBytes, StandardCharsets.UTF_8);
|
||||
Assert.assertTrue(content.contains(
|
||||
"Content-Disposition: form-data; name=\"fileType\"; filename=\"test1.json\"\r\n" +
|
||||
"Content-Type: application/json\r\n" +
|
||||
"\r\n" +
|
||||
"{}"));
|
||||
|
||||
Assert.assertTrue(content.contains(
|
||||
"Content-Disposition: form-data; name=\"fileType\"; filename=\"test2.json\"\r\n" +
|
||||
"Content-Type: application/json\r\n" +
|
||||
"\r\n" +
|
||||
"{}"));
|
||||
})
|
||||
.expectComplete()
|
||||
.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseFormData_withEncodingParamsToggleTrue_returnsEncodedString() throws UnsupportedEncodingException {
|
||||
final String encoded_value = dataUtils.parseFormData(List.of(new Property("key", "valüe")),
|
||||
|
|
@ -177,7 +212,7 @@ public class DataUtilsTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testParseFormData_withOutEncodingParamsToggleTrue_returnsEncodedString() throws UnsupportedEncodingException {
|
||||
public void testParseFormData_withoutEncodingParamsToggleTrue_returnsEncodedString() throws UnsupportedEncodingException {
|
||||
final String encoded_value = dataUtils.parseFormData(List.of(new Property("key", "valüe")),
|
||||
false);
|
||||
String expected_value = null;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user