You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by GitBox <gi...@apache.org> on 2019/01/16 10:00:07 UTC
[servicecomb-java-chassis] Diff for: [GitHub] liubao68 merged pull request
#1028: [SCB-1046] file upload support file array for the same name
diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestClientRequest.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestClientRequest.java
index a300273e8..9b360499e 100644
--- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestClientRequest.java
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestClientRequest.java
@@ -17,8 +17,6 @@
package org.apache.servicecomb.common.rest.codec;
-import javax.servlet.http.Part;
-
import io.vertx.core.MultiMap;
import io.vertx.core.buffer.Buffer;
@@ -41,5 +39,5 @@
Buffer getBodyBuffer() throws Exception;
- void attach(String name, Part part);
+ void attach(String name, Object part);
}
diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/FormProcessorCreator.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/FormProcessorCreator.java
index 04ea5bfd6..6980e94d6 100644
--- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/FormProcessorCreator.java
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/FormProcessorCreator.java
@@ -18,7 +18,9 @@
package org.apache.servicecomb.common.rest.codec.param;
import java.lang.reflect.Type;
+import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;
@@ -34,8 +36,10 @@
import io.swagger.models.parameters.FormParameter;
import io.swagger.models.parameters.Parameter;
import io.swagger.models.properties.FileProperty;
+import io.swagger.models.properties.Property;
public class FormProcessorCreator implements ParamValueProcessorCreator {
+
public static final String PARAMTYPE = "formData";
public static class FormProcessor extends AbstractParamProcessor {
@@ -99,22 +103,38 @@ public ParamValueProcessor create(Parameter parameter, Type genericParamType) {
}
private boolean isPart(Parameter parameter) {
- return new FileProperty().getType().equals(((FormParameter) parameter).getType());
+ //only check
+ FormParameter formParameter = (FormParameter) parameter;
+ if ("array".equals(formParameter.getType())) {
+ Property items = formParameter.getItems();
+ return new FileProperty().getType().equals(items.getType());
+ }
+ return new FileProperty().getType().equals(formParameter.getType());
}
- private static class PartProcessor extends AbstractParamProcessor {
+ public static class PartProcessor extends AbstractParamProcessor {
PartProcessor(String paramPath, JavaType targetType, Object defaultValue, boolean required) {
super(paramPath, targetType, defaultValue, required);
}
@Override
public Object getValue(HttpServletRequest request) throws Exception {
+ if (List.class.isAssignableFrom(targetType.getRawClass())) {
+ JavaType contentType = targetType.getContentType();
+ if (contentType != null && contentType.getRawClass().equals(Part.class)) {
+ //get all parts
+ return request.getParts()
+ .stream()
+ .filter(part -> part.getName().equals(paramPath))
+ .collect(Collectors.toList());
+ }
+ }
return request.getPart(paramPath);
}
@Override
public void setValue(RestClientRequest clientRequest, Object arg) throws Exception {
- clientRequest.attach(paramPath, (Part) arg);
+ clientRequest.attach(paramPath, arg);
}
@Override
diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/RestClientRequestImpl.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/RestClientRequestImpl.java
index 8b124ec8a..2bb92a96b 100644
--- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/RestClientRequestImpl.java
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/RestClientRequestImpl.java
@@ -24,6 +24,7 @@
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
@@ -39,6 +40,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+
import io.vertx.core.Context;
import io.vertx.core.MultiMap;
import io.vertx.core.buffer.Buffer;
@@ -52,7 +56,7 @@
protected AsyncResponse asyncResp;
- private final Map<String, Part> uploads = new HashMap<>();
+ private final Multimap<String, Part> uploads = ArrayListMultimap.create();
protected HttpClientRequest request;
@@ -80,12 +84,19 @@ public Buffer getBodyBuffer() throws Exception {
}
@Override
- public void attach(String name, Part part) {
+ @SuppressWarnings("unchecked")
+ public void attach(String name, Object part) {
if (null == part) {
LOGGER.debug("null file is ignored, file name = [{}]", name);
return;
}
- uploads.put(name, part);
+ if (List.class.isAssignableFrom(part.getClass())) {
+ List<Part> parts = (List<Part>) part;
+ uploads.putAll(name, parts);
+ return;
+ }
+ // must be part
+ uploads.put(name, (Part) part);
}
@Override
@@ -155,7 +166,7 @@ protected void doEndNormal() {
}
private void attachFiles(String boundary) {
- Iterator<Entry<String, Part>> uploadsIterator = uploads.entrySet().iterator();
+ Iterator<Entry<String, Part>> uploadsIterator = uploads.entries().iterator();
attachFile(boundary, uploadsIterator);
}
@@ -172,7 +183,6 @@ private void attachFile(String boundary, Iterator<Entry<String, Part>> uploadsIt
String name = entry.getKey();
Part part = entry.getValue();
String filename = part.getSubmittedFileName();
-
Buffer fileHeader = fileBoundaryInfo(boundary, name, part);
request.write(fileHeader);
diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestOperationMeta.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestOperationMeta.java
index a417ef22c..2c2f2fca2 100644
--- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestOperationMeta.java
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestOperationMeta.java
@@ -30,6 +30,7 @@
import javax.ws.rs.core.MediaType;
import org.apache.commons.lang3.StringUtils;
+import org.apache.servicecomb.common.rest.codec.param.FormProcessorCreator.PartProcessor;
import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor;
import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessorManager;
import org.apache.servicecomb.common.rest.definition.path.PathRegExp;
@@ -64,6 +65,8 @@
// key为参数名
protected Map<String, RestParam> paramMap = new LinkedHashMap<>();
+ protected List<String> fileKeys = new ArrayList<>();
+
// key为数据类型,比如json之类
private Map<String, ProduceProcessor> produceProcessorMap = new LinkedHashMap<>();
@@ -219,6 +222,9 @@ public URLPathBuilder getPathBuilder() {
}
private void addParam(RestParam param) {
+ if (param.getParamProcessor() instanceof PartProcessor) {
+ fileKeys.add(param.getParamName());
+ }
paramList.add(param);
paramMap.put(param.getParamName(), param);
}
@@ -258,6 +264,10 @@ public String getHttpMethod() {
return operationMeta.getHttpMethod();
}
+ public List<String> getFileKeys() {
+ return fileKeys;
+ }
+
public List<String> getProduces() {
return produces;
}
diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestRestClientRequestImpl.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestRestClientRequestImpl.java
index 137063fd4..6bcb3f9ec 100644
--- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestRestClientRequestImpl.java
+++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestRestClientRequestImpl.java
@@ -16,6 +16,7 @@
*/
package org.apache.servicecomb.common.rest.codec.param;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@@ -28,6 +29,8 @@
import org.junit.Test;
import org.mockito.Mockito;
+import com.google.common.collect.Multimap;
+
import io.vertx.core.MultiMap;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.CaseInsensitiveHeaders;
@@ -129,9 +132,9 @@ public void testAttach() {
restClientRequest.attach(fileName, part);
- Map<String, Part> uploads = Deencapsulation.getField(restClientRequest, "uploads");
+ Multimap<String, Part> uploads = Deencapsulation.getField(restClientRequest, "uploads");
Assert.assertEquals(1, uploads.size());
- Assert.assertThat(uploads, Matchers.hasEntry(fileName, part));
+ Assert.assertThat(uploads.asMap(), Matchers.hasEntry(fileName, Arrays.asList(part)));
}
@Test
@@ -140,7 +143,7 @@ public void testAttachOnPartIsNull() {
restClientRequest.attach("fileName", null);
- Map<String, Part> uploads = Deencapsulation.getField(restClientRequest, "uploads");
+ Multimap<String, Part> uploads = Deencapsulation.getField(restClientRequest, "uploads");
Assert.assertTrue(uploads.isEmpty());
}
diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxServerRequestToHttpServletRequest.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxServerRequestToHttpServletRequest.java
index 9274bc270..d7dfdccfc 100644
--- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxServerRequestToHttpServletRequest.java
+++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxServerRequestToHttpServletRequest.java
@@ -17,6 +17,7 @@
package org.apache.servicecomb.foundation.vertx.http;
+import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
@@ -24,6 +25,7 @@
import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.stream.Collectors;
import javax.servlet.AsyncContext;
import javax.servlet.ServletInputStream;
@@ -275,6 +277,12 @@ public Part getPart(String name) {
return new FileUploadPart(fileUpload);
}
+ @Override
+ public Collection<Part> getParts() {
+ Set<FileUpload> fileUploads = context.fileUploads();
+ return fileUploads.stream().map(FileUploadPart::new).collect(Collectors.toList());
+ }
+
public RoutingContext getContext() {
return context;
}
diff --git a/integration-tests/it-common/src/main/resources/logback.xml b/integration-tests/it-common/src/main/resources/logback.xml
index d753514a0..4b5920888 100644
--- a/integration-tests/it-common/src/main/resources/logback.xml
+++ b/integration-tests/it-common/src/main/resources/logback.xml
@@ -23,6 +23,7 @@
<pattern>%d [%level] [%thread] - %msg (%F:%L\)%n</pattern>
</encoder>
</appender>
+ <logger name="org.apache.servicecomb.common.javassist.JavassistUtils" level="WARN"/>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java
index 94ffdb852..0289292e2 100644
--- a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java
@@ -43,6 +43,7 @@
import org.apache.servicecomb.it.testcase.TestRestServerConfigEdge;
import org.apache.servicecomb.it.testcase.TestTrace;
import org.apache.servicecomb.it.testcase.TestTraceEdge;
+import org.apache.servicecomb.it.testcase.TestUpload;
import org.apache.servicecomb.it.testcase.base.TestGeneric;
import org.apache.servicecomb.it.testcase.thirdparty.Test3rdPartyInvocation;
@@ -106,6 +107,7 @@ private static void runShareTestCases() throws Throwable {
ITJUnitUtils.runWithRest(TestDefaultValue.class);
ITJUnitUtils.runWithRest(TestAcceptType.class);
+ ITJUnitUtils.runWithRest(TestUpload.class);
ITJUnitUtils.runWithRest(TestDownload.class);
ITJUnitUtils.runWithHighwayAndRest(TestExceptionConvertEdge.class);
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/TestUpload.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/TestUpload.java
new file mode 100644
index 000000000..d3fd5c1d6
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/TestUpload.java
@@ -0,0 +1,344 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.it.testcase;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.servicecomb.it.Consumers;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+
+public class TestUpload {
+
+ private FileSystemResource fileSystemResource1;
+
+ private FileSystemResource fileSystemResource2;
+
+ private FileSystemResource fileSystemResource3;
+
+ private FileSystemResource fileSystemResource4;
+
+ private static final String message = "cseMessage";
+
+ interface UploadIntf {
+ }
+
+ private static Consumers<UploadIntf> consumersSpringmvc = new Consumers<>("uploadSpringmvcSchema",
+ UploadIntf.class);
+
+ private static Consumers<UploadIntf> consumersJaxrs = new Consumers<>("uploadJaxrsSchema",
+ UploadIntf.class);
+
+ @Before
+ public void init() {
+ try {
+ File file1 = File.createTempFile("jaxrstest1", ".txt");
+ File file2 = File.createTempFile("测试啊", ".txt");
+ File file3 = File.createTempFile("files", ".yaml");
+ File file4 = File.createTempFile("files4", ".yaml");
+ FileUtils.writeStringToFile(file1, "hello1");
+ FileUtils.writeStringToFile(file2, "中文 2");
+ FileUtils.writeStringToFile(file3, "cse3");
+ FileUtils.writeStringToFile(file4, "cse4");
+ fileSystemResource1 = new FileSystemResource(file1);
+ fileSystemResource2 = new FileSystemResource(file2);
+ fileSystemResource3 = new FileSystemResource(file3);
+ fileSystemResource4 = new FileSystemResource(file4);
+ } catch (IOException e) {
+ Assert.fail("Failed to create temp file");
+ }
+ }
+
+ @Test
+ public void testJarxUpload1() {
+ Map<String, Object> map = new HashMap<>();
+ map.put("file1", fileSystemResource1);
+ map.put("file2", fileSystemResource2);
+ String result = consumersJaxrs.getSCBRestTemplate().postForObject("/upload1", new HttpEntity<>(map), String.class);
+ Assert.assertTrue(containsAll(result, "hello1", "中文 2"));
+ }
+
+ @Test
+ public void testJarxUploadArray1() {
+ Map<String, Object> map = new HashMap<>();
+ FileSystemResource[] arrays = {fileSystemResource1, fileSystemResource2};
+ map.put("file1", arrays);
+ map.put("file2", fileSystemResource3);
+ String result = consumersJaxrs.getSCBRestTemplate()
+ .postForObject("/uploadArray1", new HttpEntity<>(map), String.class);
+ Assert.assertTrue(containsAll(result, "hello1", "中文 2", "cse3"));
+ }
+
+ @Test
+ public void testJarxUploadList1() {
+ Map<String, Object> map = new HashMap<>();
+ List<FileSystemResource> list = new ArrayList<>();
+ list.add(fileSystemResource1);
+ list.add(fileSystemResource2);
+ map.put("file1", list);
+ map.put("file2", fileSystemResource3);
+ String result = consumersJaxrs.getSCBRestTemplate()
+ .postForObject("/uploadList1", new HttpEntity<>(map), String.class);
+ Assert.assertTrue(containsAll(result, "hello1", "中文 2", "cse3"));
+ }
+
+ @Test
+ public void testJarxUploadArrayList1() {
+ Map<String, Object> map = new HashMap<>();
+ ArrayList<FileSystemResource> list = new ArrayList<>();
+ list.add(fileSystemResource1);
+ list.add(fileSystemResource2);
+ map.put("file1", list);
+ map.put("file2", fileSystemResource3);
+ String result = consumersJaxrs.getSCBRestTemplate()
+ .postForObject("/uploadArrayList1", new HttpEntity<>(map), String.class);
+ Assert.assertTrue(containsAll(result, "hello1", "中文 2", "cse3"));
+ }
+
+ @Test
+ public void testJarxUpload2() {
+ Map<String, Object> map = new HashMap<>();
+ map.put("file1", fileSystemResource1);
+ map.put("message", message);
+ String result = consumersJaxrs.getSCBRestTemplate()
+ .postForObject("/upload2", new HttpEntity<>(map), String.class);
+ Assert.assertTrue(containsAll(result, "hello1", message));
+ }
+
+ @Test
+ public void testJarxUploadArray2() {
+ Map<String, Object> map = new HashMap<>();
+ FileSystemResource[] arrays = {fileSystemResource1, fileSystemResource2};
+ map.put("file1", arrays);
+ map.put("message", message);
+ String result = consumersJaxrs.getSCBRestTemplate()
+ .postForObject("/uploadArray2", new HttpEntity<>(map), String.class);
+ Assert.assertTrue(containsAll(result, "hello1", "中文 2", message));
+ }
+
+ @Test
+ public void testJarxUploadList2() {
+ Map<String, Object> map = new HashMap<>();
+ List<FileSystemResource> list = new ArrayList<>();
+ list.add(fileSystemResource2);
+ list.add(fileSystemResource3);
+ map.put("file1", list);
+ map.put("message", message);
+ String result = consumersJaxrs.getSCBRestTemplate()
+ .postForObject("/uploadList2", new HttpEntity<>(map), String.class);
+ Assert.assertTrue(containsAll(result, "cse3", "中文 2", message));
+ }
+
+ @Test
+ public void testJarxUploadArrayList2() {
+ Map<String, Object> map = new HashMap<>();
+ ArrayList<FileSystemResource> list = new ArrayList<>();
+ list.add(fileSystemResource2);
+ list.add(fileSystemResource3);
+ map.put("file1", list);
+ map.put("message", message);
+ String result = consumersJaxrs.getSCBRestTemplate()
+ .postForObject("/uploadArrayList2", new HttpEntity<>(map), String.class);
+ Assert.assertTrue(containsAll(result, "cse3", "中文 2", message));
+ }
+
+ @Test
+ public void testJarxUploadMix() {
+ Map<String, Object> map = new HashMap<>();
+ List<FileSystemResource> list = new ArrayList<>();
+ list.add(fileSystemResource4);
+ list.add(fileSystemResource3);
+ FileSystemResource[] arrays = {fileSystemResource1, fileSystemResource2};
+ map.put("file1", list);
+ map.put("file2", arrays);
+ map.put("message", message);
+ String result = consumersJaxrs.getSCBRestTemplate()
+ .postForObject("/uploadMix", new HttpEntity<>(map), String.class);
+ Assert.assertTrue(containsAll(result, "hello1", "cse4", "cse3", "中文 2", message));
+ }
+
+ //springmvc
+ @Test
+ public void testFileUpload() {
+ Map<String, Object> map = new HashMap<>();
+ map.put("file1", fileSystemResource1);
+ map.put("file2", fileSystemResource2);
+ map.put("name", message);
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.MULTIPART_FORM_DATA);
+ String result = consumersSpringmvc.getSCBRestTemplate().postForObject("/upload",
+ new HttpEntity<>(map, headers), String.class);
+ Assert.assertTrue(containsAll(result, "hello1", "中文 2", message));
+ }
+
+ @Test
+ public void testFileUploadArray() {
+ Map<String, Object> map = new HashMap<>();
+ FileSystemResource[] array1 = {fileSystemResource1, fileSystemResource2};
+ FileSystemResource[] array2 = {fileSystemResource3, fileSystemResource4};
+ map.put("file1", array1);
+ map.put("file2", array2);
+ map.put("name", message);
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.MULTIPART_FORM_DATA);
+ String result = consumersSpringmvc.getSCBRestTemplate()
+ .postForObject("/uploadArray", new HttpEntity<>(map, headers), String.class);
+ Assert.assertTrue(containsAll(result, "hello1", "cse4", "cse3", "中文 2", message));
+ }
+
+ @Test
+ public void testFileUploadList() {
+ Map<String, Object> map = new HashMap<>();
+ List<FileSystemResource> list1 = new ArrayList<>();
+ List<FileSystemResource> list2 = new ArrayList<>();
+ list1.add(fileSystemResource1);
+ list1.add(fileSystemResource2);
+ list2.add(fileSystemResource3);
+ list2.add(fileSystemResource4);
+ map.put("file1", list1);
+ map.put("file2", list2);
+ map.put("name", message);
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.MULTIPART_FORM_DATA);
+ String result = consumersSpringmvc.getSCBRestTemplate()
+ .postForObject("/uploadList", new HttpEntity<>(map, headers), String.class);
+ Assert.assertTrue(containsAll(result, "hello1", "cse4", "cse3", "中文 2", message));
+ }
+
+ @Test
+ public void testFileUploadArrayList() {
+ Map<String, Object> map = new HashMap<>();
+ ArrayList<FileSystemResource> list1 = new ArrayList<>();
+ ArrayList<FileSystemResource> list2 = new ArrayList<>();
+ list1.add(fileSystemResource1);
+ list1.add(fileSystemResource2);
+ list2.add(fileSystemResource3);
+ list2.add(fileSystemResource4);
+ map.put("file1", list1);
+ map.put("file2", list2);
+ map.put("name", message);
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.MULTIPART_FORM_DATA);
+ String result = consumersSpringmvc.getSCBRestTemplate()
+ .postForObject("/uploadArrayList", new HttpEntity<>(map, headers), String.class);
+ Assert.assertTrue(containsAll(result, "hello1", "cse4", "cse3", "中文 2", message));
+ }
+
+ @Test
+ public void testFileUploadWithoutAnnotation() {
+ Map<String, Object> map = new HashMap<>();
+ map.put("file1", fileSystemResource1);
+ map.put("file2", fileSystemResource2);
+ map.put("name", message);
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.MULTIPART_FORM_DATA);
+ String result = consumersSpringmvc.getSCBRestTemplate().postForObject("/uploadWithoutAnnotation",
+ new HttpEntity<>(map, headers), String.class);
+ Assert.assertTrue(containsAll(result, "hello1", "中文 2", message));
+ }
+
+ @Test
+ public void testFileUploadArrayWithoutAnnotation() {
+ Map<String, Object> map = new HashMap<>();
+ FileSystemResource[] array1 = {fileSystemResource1, fileSystemResource2};
+ FileSystemResource[] array2 = {fileSystemResource3, fileSystemResource4};
+ map.put("file1", array1);
+ map.put("file2", array2);
+ map.put("name", message);
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.MULTIPART_FORM_DATA);
+ String result = consumersSpringmvc.getSCBRestTemplate()
+ .postForObject("/uploadArrayWithoutAnnotation", new HttpEntity<>(map, headers), String.class);
+ Assert.assertTrue(containsAll(result, "hello1", "cse4", "cse3", "中文 2", message));
+ }
+
+ @Test
+ public void testFileUploadListWithoutAnnotation() {
+ Map<String, Object> map = new HashMap<>();
+ List<FileSystemResource> list1 = new ArrayList<>();
+ List<FileSystemResource> list2 = new ArrayList<>();
+ list1.add(fileSystemResource1);
+ list1.add(fileSystemResource2);
+ list2.add(fileSystemResource3);
+ list2.add(fileSystemResource4);
+ map.put("file1", list1);
+ map.put("file2", list2);
+ map.put("name", message);
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.MULTIPART_FORM_DATA);
+ String result = consumersSpringmvc.getSCBRestTemplate()
+ .postForObject("/uploadListArrayWithoutAnnotation", new HttpEntity<>(map, headers), String.class);
+ Assert.assertTrue(containsAll(result, "hello1", "cse4", "cse3", "中文 2", message));
+ }
+
+ @Test
+ public void testFileUploadArrayListWithoutAnnotation() {
+ Map<String, Object> map = new HashMap<>();
+ ArrayList<FileSystemResource> list1 = new ArrayList<>();
+ ArrayList<FileSystemResource> list2 = new ArrayList<>();
+ list1.add(fileSystemResource1);
+ list1.add(fileSystemResource2);
+ list2.add(fileSystemResource3);
+ list2.add(fileSystemResource4);
+ map.put("file1", list1);
+ map.put("file2", list2);
+ map.put("name", message);
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.MULTIPART_FORM_DATA);
+ String result = consumersSpringmvc.getSCBRestTemplate()
+ .postForObject("/uploadArrayListArrayWithoutAnnotation", new HttpEntity<>(map, headers), String.class);
+ Assert.assertTrue(containsAll(result, "hello1", "cse4", "cse3", "中文 2", message));
+ }
+
+ @Test
+ public void testFileUploadMixWithoutAnnotation() {
+ Map<String, Object> map = new HashMap<>();
+ List<FileSystemResource> list1 = new ArrayList<>();
+ list1.add(fileSystemResource1);
+ list1.add(fileSystemResource2);
+ FileSystemResource[] array2 = {fileSystemResource3, fileSystemResource4};
+ map.put("file1", list1);
+ map.put("file2", array2);
+ map.put("name", message);
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.MULTIPART_FORM_DATA);
+ String result = consumersSpringmvc.getSCBRestTemplate()
+ .postForObject("/uploadMix", new HttpEntity<>(map, headers), String.class);
+ Assert.assertTrue(containsAll(result, "hello1", "cse4", "cse3", "中文 2", message));
+ }
+
+
+ private static boolean containsAll(String str, String... strings) {
+ for (String string : strings) {
+ if (!str.contains(string)) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/UploadJaxrsSchema.java b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/UploadJaxrsSchema.java
new file mode 100644
index 000000000..6dccf710b
--- /dev/null
+++ b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/UploadJaxrsSchema.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.it.schema;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.Part;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+
+@RestSchema(schemaId = "uploadJaxrsSchema")
+@Path("/v1/uploadJaxrsSchema")
+public class UploadJaxrsSchema {
+ @Path("/upload1")
+ @POST
+ @Produces(MediaType.TEXT_PLAIN)
+ public String fileUpload1(@FormParam("file1") Part file1, @FormParam("file2") Part file2) throws IOException {
+ return getStrFromPart(file1) + getStrFromPart(file2);
+ }
+
+ @Path("/uploadArray1")
+ @POST
+ @Produces(MediaType.TEXT_PLAIN)
+ public String uploadArray1(@FormParam("file1") Part[] file1, @FormParam("file2") Part file2) throws IOException {
+ StringBuilder stringBuilder = new StringBuilder();
+ for (int i = 0; i < file1.length; i++) {
+ stringBuilder.append(getStrFromPart(file1[i]));
+ }
+ return stringBuilder.append(getStrFromPart(file2)).toString();
+ }
+
+
+ @Path("/uploadList1")
+ @POST
+ @Produces(MediaType.TEXT_PLAIN)
+ public String uploadList1(@FormParam("file1") List<Part> file1, @FormParam("file2") Part file2)
+ throws IOException {
+ StringBuilder stringBuilder = new StringBuilder();
+ file1.forEach(part -> {
+ stringBuilder.append(getStrFromPart(part));
+ });
+ return stringBuilder.append(getStrFromPart(file2)).toString();
+ }
+
+ @Path("/uploadArrayList1")
+ @POST
+ @Produces(MediaType.TEXT_PLAIN)
+ public String uploadArrayList1(@FormParam("file1") ArrayList<Part> file1, @FormParam("file2") Part file2)
+ throws IOException {
+ StringBuilder stringBuilder = new StringBuilder();
+ file1.forEach(part -> {
+ stringBuilder.append(getStrFromPart(part));
+ });
+ return stringBuilder.append(getStrFromPart(file2)).toString();
+ }
+
+
+ @Path("/upload2")
+ @POST
+ @Produces(MediaType.TEXT_PLAIN)
+ public String fileUpload2(@FormParam("file1") Part file1, @FormParam("message") String message) throws IOException {
+ return getStrFromPart(file1) + message;
+ }
+
+ @Path("/uploadArray2")
+ @POST
+ @Produces(MediaType.TEXT_PLAIN)
+ public String uploadArray2(@FormParam("file1") Part[] file1, @FormParam("message") String message)
+ throws IOException {
+ StringBuilder stringBuilder = new StringBuilder();
+ for (int i = 0; i < file1.length; i++) {
+ stringBuilder.append(getStrFromPart(file1[i]));
+ }
+ return stringBuilder.append(message).toString();
+ }
+
+
+ @Path("/uploadList2")
+ @POST
+ @Produces(MediaType.TEXT_PLAIN)
+ public String uploadList2(@FormParam("file1") List<Part> file1, @FormParam("message") String message) {
+ StringBuilder stringBuilder = new StringBuilder();
+ file1.forEach(part -> {
+ stringBuilder.append(getStrFromPart(part));
+ });
+ return stringBuilder.append(message).toString();
+ }
+
+ @Path("/uploadArrayList2")
+ @POST
+ @Produces(MediaType.TEXT_PLAIN)
+ public String uploadArrayList2(@FormParam("file1") ArrayList<Part> file1, @FormParam("message") String message) {
+ StringBuilder stringBuilder = new StringBuilder();
+ file1.forEach(part -> {
+ stringBuilder.append(getStrFromPart(part));
+ });
+ return stringBuilder.append(message).toString();
+ }
+
+ @Path("/uploadMix")
+ @POST
+ @Produces(MediaType.TEXT_PLAIN)
+ public String uploadMix(@FormParam("file1") List<Part> file1, @FormParam("file2") Part[] file2,
+ @FormParam("message") String message) {
+ StringBuilder stringBuilder = new StringBuilder();
+ file1.forEach(part -> {
+ stringBuilder.append(getStrFromPart(part));
+ });
+ for (int i = 0; i < file2.length; i++) {
+ stringBuilder.append(getStrFromPart(file2[i]));
+ }
+ return stringBuilder.append(message).toString();
+ }
+
+ private static String getStrFromPart(Part file1) {
+ try (InputStream is1 = file1.getInputStream()) {
+ return IOUtils.toString(is1, "utf-8");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+}
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/UploadSpringmvcSchema.java b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/UploadSpringmvcSchema.java
new file mode 100644
index 000000000..d77570c7a
--- /dev/null
+++ b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/UploadSpringmvcSchema.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.it.schema;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.RequestAttribute;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestPart;
+import org.springframework.web.multipart.MultipartFile;
+
+import com.google.common.collect.Lists;
+
+
+@RestSchema(schemaId = "uploadSpringmvcSchema")
+@RequestMapping(path = "/v1/uploadSpringmvcSchema")
+public class UploadSpringmvcSchema {
+
+ @RequestMapping(path = "/upload", method = RequestMethod.POST, produces = MediaType.TEXT_PLAIN_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+ public String fileUpload(@RequestPart(name = "file1") MultipartFile file1,
+ @RequestPart(name = "file2") MultipartFile file2, @RequestAttribute("name") String name) {
+ return _fileUpload(Lists.newArrayList(file1, file2)) + name;
+ }
+
+ @RequestMapping(path = "/uploadArray", method = RequestMethod.POST, produces = MediaType.TEXT_PLAIN_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+ public String fileUploadArray(@RequestPart(name = "file1") MultipartFile[] file1,
+ @RequestPart(name = "file2") MultipartFile[] file2, @RequestAttribute("name") String name) {
+ List<MultipartFile> multipartFileList = new ArrayList<>();
+ multipartFileList.addAll(Arrays.asList(file1));
+ multipartFileList.addAll(Arrays.asList(file2));
+ return _fileUpload(multipartFileList) + name;
+ }
+
+ @RequestMapping(path = "/uploadList", method = RequestMethod.POST, produces = MediaType.TEXT_PLAIN_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+ public String fileUploadList(@RequestPart(name = "file1") List<MultipartFile> file1,
+ @RequestPart(name = "file2") List<MultipartFile> file2, @RequestAttribute("name") String name) {
+ file1.addAll(file2);
+ return _fileUpload(file1) + name;
+ }
+
+ @RequestMapping(path = "/uploadArrayList", method = RequestMethod.POST, produces = MediaType.TEXT_PLAIN_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+ public String fileUploadArrayList(@RequestPart(name = "file1") ArrayList<MultipartFile> file1,
+ @RequestPart(name = "file2") ArrayList<MultipartFile> file2, @RequestAttribute("name") String name) {
+ file1.addAll(file2);
+ return _fileUpload(file1) + name;
+ }
+
+ @RequestMapping(path = "/uploadWithoutAnnotation", method = RequestMethod.POST, produces = MediaType.TEXT_PLAIN_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+ public String uploadWithoutAnnotation(MultipartFile file1, MultipartFile file2,
+ @RequestAttribute("name") String name) {
+ return _fileUpload(Lists.newArrayList(file1, file2)) + name;
+ }
+
+ @RequestMapping(path = "/uploadArrayWithoutAnnotation", method = RequestMethod.POST, produces = MediaType.TEXT_PLAIN_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+ public String uploadArrayWithoutAnnotation(MultipartFile[] file1, MultipartFile[] file2,
+ @RequestAttribute("name") String name) {
+ List<MultipartFile> multipartFileList = new ArrayList<>();
+ multipartFileList.addAll(Arrays.asList(file1));
+ multipartFileList.addAll(Arrays.asList(file2));
+ return _fileUpload(multipartFileList) + name;
+ }
+
+ @RequestMapping(path = "/uploadListArrayWithoutAnnotation", method = RequestMethod.POST, produces = MediaType.TEXT_PLAIN_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+ public String uploadListWithoutAnnotation(List<MultipartFile> file1, List<MultipartFile> file2,
+ @RequestAttribute("name") String name) {
+ file1.addAll(file2);
+ return _fileUpload(file1) + name;
+ }
+
+ @RequestMapping(path = "/uploadArrayListArrayWithoutAnnotation", method = RequestMethod.POST, produces = MediaType.TEXT_PLAIN_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+ public String uploadArrayListWithoutAnnotation(ArrayList<MultipartFile> file1, ArrayList<MultipartFile> file2,
+ @RequestAttribute("name") String name) {
+ file1.addAll(file2);
+ return _fileUpload(file1) + name;
+ }
+
+ @RequestMapping(path = "/uploadMix", method = RequestMethod.POST, produces = MediaType.TEXT_PLAIN_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+ public String uploadMix(@RequestPart(name = "file1") List<MultipartFile> file1,
+ @RequestPart(name = "file2") MultipartFile[] file2, @RequestAttribute("name") String name) {
+ List<MultipartFile> multipartFileList = Arrays.asList(file2);
+ file1.addAll(multipartFileList);
+ return _fileUpload(file1) + name;
+ }
+
+ private static String _fileUpload(List<MultipartFile> fileList) {
+ StringBuilder stringBuilder = new StringBuilder();
+ try {
+ for (MultipartFile multipartFile : fileList) {
+ stringBuilder.append(IOUtils.toString(multipartFile.getBytes(), StandardCharsets.UTF_8.name()));
+ }
+ } catch (IOException e) {
+ throw new IllegalArgumentException(e);
+ }
+ return stringBuilder.toString();
+ }
+}
diff --git a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CommonToHttpServletRequest.java b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CommonToHttpServletRequest.java
index 2d5d75ed8..5bfe5e3f5 100644
--- a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CommonToHttpServletRequest.java
+++ b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CommonToHttpServletRequest.java
@@ -29,7 +29,6 @@
import java.util.List;
import java.util.Map;
-import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.Part;
@@ -42,20 +41,25 @@
import org.apache.servicecomb.foundation.vertx.http.AbstractHttpServletRequest;
import org.springframework.core.io.Resource;
+import com.google.common.annotations.VisibleForTesting;
+
// restTemplate convert parameters to invocation args.
public class CommonToHttpServletRequest extends AbstractHttpServletRequest {
private Map<String, List<String>> queryParams;
private Map<String, List<String>> httpHeaders;
+ //contains all the file key in the parts
+ private List<String> fileKeys = new ArrayList<>();
+
// gen by httpHeaders
private Cookie[] cookies;
@SuppressWarnings("unchecked")
public CommonToHttpServletRequest(Map<String, String> pathParams, Map<String, List<String>> queryParams,
- Map<String, List<String>> httpHeaders, Object bodyObject, boolean isFormData) {
+ Map<String, List<String>> httpHeaders, Object bodyObject, boolean isFormData, List<String> fileKeys) {
setAttribute(RestConst.PATH_PARAMETERS, pathParams);
-
+ this.fileKeys = fileKeys;
if (isFormData) {
setAttribute(RestConst.FORM_PARAMETERS, (Map<String, Object>) bodyObject);
} else {
@@ -66,6 +70,12 @@ public CommonToHttpServletRequest(Map<String, String> pathParams, Map<String, Li
this.httpHeaders = httpHeaders;
}
+ @SuppressWarnings("unchecked")
+ public CommonToHttpServletRequest(Map<String, String> pathParams, Map<String, List<String>> queryParams,
+ Map<String, List<String>> httpHeaders, Object bodyObject, boolean isFormData) {
+ this(pathParams, queryParams, httpHeaders, bodyObject, isFormData, null);
+ }
+
@Override
public String getContentType() {
return getHeader(HttpHeaders.CONTENT_TYPE);
@@ -164,8 +174,12 @@ public void addHeader(String name, String value) {
}
@Override
- public Part getPart(String name) throws IOException, ServletException {
+ public Part getPart(String name) {
Object value = findPartInputValue(name);
+ return getSinglePart(name, value);
+ }
+
+ private Part getSinglePart(String name, Object value) {
if (value == null) {
return null;
}
@@ -196,6 +210,39 @@ public Part getPart(String name) throws IOException, ServletException {
value.getClass().getName()));
}
+ @Override
+ public Collection<Part> getParts() {
+ @SuppressWarnings("unchecked")
+ Map<String, Object> form = (Map<String, Object>) getAttribute(RestConst.FORM_PARAMETERS);
+ List<Part> partList = new ArrayList<>();
+ filePartListWithForm(partList, form);
+ return partList;
+ }
+
+ private void filePartListWithForm(List<Part> partList, Map<String, Object> form) {
+ for (String key : fileKeys) {
+ Object value = form.get(key);
+ if (value == null) {
+ continue;
+ }
+ if (Collection.class.isInstance(value)) {
+ Collection<?> collection = (Collection<?>) value;
+ for (Object part : collection) {
+ partList.add(getSinglePart(key, part));
+ }
+ continue;
+ }
+ if (value.getClass().isArray()) {
+ Object[] params = (Object[]) value;
+ for (int i = 0; i < params.length; i++) {
+ partList.add(getSinglePart(key, params[i]));
+ }
+ continue;
+ }
+ partList.add(getSinglePart(key, value));
+ }
+ }
+
protected Object findPartInputValue(String name) {
@SuppressWarnings("unchecked")
Map<String, Object> form = (Map<String, Object>) getAttribute(RestConst.FORM_PARAMETERS);
@@ -214,4 +261,9 @@ protected Object findPartInputValue(String name) {
}
return value;
}
+
+ @VisibleForTesting
+ public List<String> getFileKeys() {
+ return fileKeys;
+ }
}
diff --git a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java
index 6f3388396..119139171 100644
--- a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java
+++ b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java
@@ -206,7 +206,8 @@ protected Response doInvoke(Invocation invocation) {
protected Object[] collectArguments() {
HttpServletRequest mockRequest = new CommonToHttpServletRequest(requestMeta.getPathParams(), queryParams,
- httpHeaders, requestBody, requestMeta.getSwaggerRestOperation().isFormData());
+ httpHeaders, requestBody, requestMeta.getSwaggerRestOperation().isFormData(),
+ requestMeta.getSwaggerRestOperation().getFileKeys());
return RestCodec.restToArgs(mockRequest, requestMeta.getSwaggerRestOperation());
}
}
diff --git a/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/TestCommonToHttpServletRequest.java b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/TestCommonToHttpServletRequest.java
index d0522cd77..6461e6aed 100644
--- a/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/TestCommonToHttpServletRequest.java
+++ b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/TestCommonToHttpServletRequest.java
@@ -17,8 +17,11 @@
package org.apache.servicecomb.provider.springmvc.reference;
+import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -26,6 +29,7 @@
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.Part;
import javax.ws.rs.core.HttpHeaders;
import org.apache.servicecomb.common.rest.RestConst;
@@ -53,6 +57,17 @@ public void testConstructFormFalse() {
Assert.assertEquals(body, request.getAttribute(RestConst.BODY_PARAMETER));
}
+ @Test
+ public void testConstructNormal() {
+ List<String> fileKeys = new ArrayList<>();
+ fileKeys.add("test1");
+ fileKeys.add("test2");
+ HttpServletRequest request = new CommonToHttpServletRequest(null, null, null, null, false, fileKeys);
+ Assert.assertEquals(2, ((CommonToHttpServletRequest) request).getFileKeys().size());
+ Assert.assertEquals("test1", ((CommonToHttpServletRequest) request).getFileKeys().get(0));
+ Assert.assertEquals("test2", ((CommonToHttpServletRequest) request).getFileKeys().get(1));
+ }
+
@Test
public void testConstructPath() {
Map<String, String> pathParams = new HashMap<>();
@@ -235,4 +250,34 @@ public void testAddHeader() {
request.addHeader("name", "v2");
Assert.assertThat(Collections.list(request.getHeaders("name")), Matchers.contains("v1", "v2"));
}
+
+ @Test
+ public void testGetParts() {
+ List<String> restParams = new ArrayList<>();
+ restParams.add("test1");
+ restParams.add("test2");
+ File file1 = new File("file1.txt");
+ File file2 = new File("file2.txt");
+ File[] files = {file1, file2};
+ List<File> list = Arrays.asList(files);
+ Map<String, Object> objectMap = new HashMap<>();
+ objectMap.put("test1", list);
+ objectMap.put("test2", files);
+ objectMap.put("test3", list);
+ objectMap.put("test4", "haha");
+
+ Map<String, String> pathParams = new HashMap<>();
+ HttpServletRequest request = new CommonToHttpServletRequest(pathParams, null, null, objectMap, true, restParams);
+ try {
+ Collection<Part> tmpParts = request.getParts();
+ ArrayList<Part> parts = new ArrayList<>(tmpParts);
+ Assert.assertEquals(4, parts.size());
+ Assert.assertEquals("test1", parts.get(0).getName());
+ Assert.assertEquals("test1", parts.get(1).getName());
+ Assert.assertEquals("test2", parts.get(2).getName());
+ Assert.assertEquals("test2", parts.get(3).getName());
+ } catch (Throwable e) {
+ Assert.fail("should not throw exception");
+ }
+ }
}
diff --git a/swagger/swagger-generator/generator-core/pom.xml b/swagger/swagger-generator/generator-core/pom.xml
index fd22a22f4..924467b3c 100644
--- a/swagger/swagger-generator/generator-core/pom.xml
+++ b/swagger/swagger-generator/generator-core/pom.xml
@@ -65,6 +65,10 @@
<artifactId>log4j</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>com.google.inject</groupId>
+ <artifactId>guice</artifactId>
+ </dependency>
<dependency>
<groupId>org.apache.servicecomb</groupId>
<artifactId>foundation-test-scaffolding</artifactId>
diff --git a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/CommonParameterTypeProcessor.java b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/CommonParameterTypeProcessor.java
index 789cdcaa5..1b32f274a 100644
--- a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/CommonParameterTypeProcessor.java
+++ b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/CommonParameterTypeProcessor.java
@@ -17,9 +17,12 @@
package org.apache.servicecomb.swagger.generator.core;
+
+import java.lang.reflect.Type;
+
/**
* 通过spi自动注入到所有的GeneratorContext实例中去
*/
public interface CommonParameterTypeProcessor extends ParameterTypeProcessor {
- Class<?> getParameterType();
+ Type getParameterType();
}
diff --git a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/OperationGenerator.java b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/OperationGenerator.java
index 8c9a83429..feacd86dc 100644
--- a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/OperationGenerator.java
+++ b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/OperationGenerator.java
@@ -19,6 +19,7 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
@@ -37,6 +38,8 @@
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
+import com.google.inject.util.Types;
+
import io.swagger.models.HttpMethod;
import io.swagger.models.Operation;
import io.swagger.models.Path;
@@ -344,11 +347,30 @@ protected void processByParameterAnnotation(Annotation[] paramAnnotations, int p
protected void processByParameterType(Type parameterType, int paramIdx) {
ParameterTypeProcessor processor = context.findParameterTypeProcessor(parameterType);
+ if (processor == null) {
+ //maybe is ArrayList ...
+ Type realType = checkAndGetType(parameterType);
+ if (realType != null) {
+ processor = context.findParameterTypeProcessor(realType);
+ }
+ }
if (processor != null) {
processor.process(this, paramIdx);
}
}
+ // check whether is ArrayList , LinkedArrayList ... or not
+ private Type checkAndGetType(Type type) {
+ if (ParameterizedType.class.isAssignableFrom(type.getClass())) {
+ ParameterizedType targetType = (ParameterizedType) type;
+ Class<?> targetCls = (Class<?>) targetType.getRawType();
+ if (List.class.isAssignableFrom(targetCls)) {
+ return Types.newParameterizedType(List.class, (Class<?>) targetType.getActualTypeArguments()[0]);
+ }
+ }
+ return null;
+ }
+
public void correctOperation() {
if (StringUtils.isEmpty(operation.getOperationId())) {
operation.setOperationId(providerMethod.getName());
diff --git a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/processor/parametertype/HttpServletRequestProcessor.java b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/processor/parametertype/HttpServletRequestProcessor.java
index 3b5bb0dc1..731d2db0e 100644
--- a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/processor/parametertype/HttpServletRequestProcessor.java
+++ b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/processor/parametertype/HttpServletRequestProcessor.java
@@ -17,6 +17,8 @@
package org.apache.servicecomb.swagger.generator.core.processor.parametertype;
+import java.lang.reflect.Type;
+
import javax.servlet.http.HttpServletRequest;
import org.apache.servicecomb.swagger.extend.parameter.HttpRequestParameter;
@@ -25,7 +27,7 @@
public class HttpServletRequestProcessor implements CommonParameterTypeProcessor {
@Override
- public Class<?> getParameterType() {
+ public Type getParameterType() {
return HttpServletRequest.class;
}
diff --git a/swagger/swagger-generator/generator-springmvc/pom.xml b/swagger/swagger-generator/generator-springmvc/pom.xml
index 94b59394f..5e8b4f679 100644
--- a/swagger/swagger-generator/generator-springmvc/pom.xml
+++ b/swagger/swagger-generator/generator-springmvc/pom.xml
@@ -45,6 +45,10 @@
<artifactId>log4j</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>com.google.inject</groupId>
+ <artifactId>guice</artifactId>
+ </dependency>
<dependency>
<groupId>org.apache.servicecomb</groupId>
<artifactId>foundation-test-scaffolding</artifactId>
diff --git a/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/MultipartFileArrayTypeProcessor.java b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/MultipartFileArrayTypeProcessor.java
new file mode 100644
index 000000000..4b040c0ba
--- /dev/null
+++ b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/MultipartFileArrayTypeProcessor.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.swagger.generator.springmvc.processor.parameter;
+
+import java.lang.reflect.Type;
+
+import org.apache.servicecomb.swagger.generator.core.CommonParameterTypeProcessor;
+import org.apache.servicecomb.swagger.generator.core.OperationGenerator;
+import org.apache.servicecomb.swagger.generator.core.utils.ParamUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+import io.swagger.models.parameters.FormParameter;
+import io.swagger.models.properties.ArrayProperty;
+import io.swagger.models.properties.FileProperty;
+import io.swagger.models.properties.Property;
+
+public class MultipartFileArrayTypeProcessor implements CommonParameterTypeProcessor {
+ @Override
+ public Type getParameterType() {
+ return MultipartFile[].class;
+ }
+
+ @Override
+ public void process(OperationGenerator operationGenerator, int paramIdx) {
+ FormParameter parameter = new FormParameter();
+ parameter.setName(ParamUtils.getParameterName(operationGenerator.getProviderMethod(), paramIdx));
+ Property property = new ArrayProperty(new FileProperty());
+ parameter.setProperty(property);
+ operationGenerator.addProviderParameter(parameter);
+ }
+}
diff --git a/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/MultipartFileListTypeProcessor.java b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/MultipartFileListTypeProcessor.java
new file mode 100644
index 000000000..289ecddf8
--- /dev/null
+++ b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/MultipartFileListTypeProcessor.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.swagger.generator.springmvc.processor.parameter;
+
+import java.lang.reflect.Type;
+import java.util.List;
+
+import org.apache.servicecomb.swagger.generator.core.CommonParameterTypeProcessor;
+import org.apache.servicecomb.swagger.generator.core.OperationGenerator;
+import org.apache.servicecomb.swagger.generator.core.utils.ParamUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+import com.google.inject.util.Types;
+
+import io.swagger.models.parameters.FormParameter;
+import io.swagger.models.properties.ArrayProperty;
+import io.swagger.models.properties.FileProperty;
+import io.swagger.models.properties.Property;
+
+public class MultipartFileListTypeProcessor implements CommonParameterTypeProcessor {
+
+ @Override
+ public Type getParameterType() {
+ return Types.newParameterizedType(List.class, MultipartFile.class);
+ }
+
+ @Override
+ public void process(OperationGenerator operationGenerator, int paramIdx) {
+ FormParameter parameter = new FormParameter();
+ parameter.setName(ParamUtils.getParameterName(operationGenerator.getProviderMethod(), paramIdx));
+ Property property = new ArrayProperty(new FileProperty());
+ parameter.setProperty(property);
+ operationGenerator.addProviderParameter(parameter);
+ }
+}
diff --git a/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/MultipartFileTypeProcessor.java b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/MultipartFileTypeProcessor.java
index 12e4974b5..8d0972d0d 100644
--- a/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/MultipartFileTypeProcessor.java
+++ b/swagger/swagger-generator/generator-springmvc/src/main/java/org/apache/servicecomb/swagger/generator/springmvc/processor/parameter/MultipartFileTypeProcessor.java
@@ -17,6 +17,8 @@
package org.apache.servicecomb.swagger.generator.springmvc.processor.parameter;
+import java.lang.reflect.Type;
+
import org.apache.servicecomb.swagger.generator.core.CommonParameterTypeProcessor;
import org.apache.servicecomb.swagger.generator.core.OperationGenerator;
import org.apache.servicecomb.swagger.generator.core.utils.ParamUtils;
@@ -27,7 +29,7 @@
public class MultipartFileTypeProcessor implements CommonParameterTypeProcessor {
@Override
- public Class<?> getParameterType() {
+ public Type getParameterType() {
return MultipartFile.class;
}
diff --git a/swagger/swagger-generator/generator-springmvc/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.generator.core.CommonParameterTypeProcessor b/swagger/swagger-generator/generator-springmvc/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.generator.core.CommonParameterTypeProcessor
index 0bad0b7e0..bea33a134 100644
--- a/swagger/swagger-generator/generator-springmvc/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.generator.core.CommonParameterTypeProcessor
+++ b/swagger/swagger-generator/generator-springmvc/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.generator.core.CommonParameterTypeProcessor
@@ -16,3 +16,5 @@
#
org.apache.servicecomb.swagger.generator.springmvc.processor.parameter.MultipartFileTypeProcessor
+org.apache.servicecomb.swagger.generator.springmvc.processor.parameter.MultipartFileArrayTypeProcessor
+org.apache.servicecomb.swagger.generator.springmvc.processor.parameter.MultipartFileListTypeProcessor
\ No newline at end of file
diff --git a/swagger/swagger-invocation/invocation-core/pom.xml b/swagger/swagger-invocation/invocation-core/pom.xml
index 3dd32e48e..34b06c8f4 100644
--- a/swagger/swagger-invocation/invocation-core/pom.xml
+++ b/swagger/swagger-invocation/invocation-core/pom.xml
@@ -28,6 +28,10 @@
<dependencies>
+ <dependency>
+ <groupId>com.google.inject</groupId>
+ <artifactId>guice</artifactId>
+ </dependency>
<dependency>
<groupId>org.apache.servicecomb</groupId>
<artifactId>swagger-generator-core</artifactId>
diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/converter/ConverterMgr.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/converter/ConverterMgr.java
index 94b8570d0..faf65ecb4 100644
--- a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/converter/ConverterMgr.java
+++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/converter/ConverterMgr.java
@@ -37,6 +37,8 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
+import com.google.inject.util.Types;
+
@Component
public class ConverterMgr {
private static final Logger LOGGER = LoggerFactory.getLogger(ConverterMgr.class);
@@ -99,13 +101,33 @@ public Converter findConverter(Type src, Type target) {
return findCommonConverter(target);
}
+
protected Converter findSrcTarget(Type src, Type target) {
Map<Type, Converter> map = srcTargetMap.get(src);
- if (map == null) {
- return null;
+ if (map != null) {
+ Converter converter = map.get(target);
+ if (converter == null) {
+ //maybe target class is ArrayList...
+ Type realTarget = checkAndGetType(target);
+ if (realTarget != null) {
+ converter = map.get(realTarget);
+ }
+ }
+ return converter;
}
+ return null;
+ }
- return map.get(target);
+ // check whether is ArrayList , LinkedArrayList ... or not
+ private Type checkAndGetType(Type type) {
+ if (ParameterizedType.class.isAssignableFrom(type.getClass())) {
+ ParameterizedType targetType = (ParameterizedType) type;
+ Class<?> targetCls = (Class<?>) targetType.getRawType();
+ if (List.class.isAssignableFrom(targetCls)) {
+ return Types.newParameterizedType(List.class, (Class<?>) targetType.getActualTypeArguments()[0]);
+ }
+ }
+ return null;
}
protected Converter findCommonConverter(Type target) {
diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/generator/InvocationContextProcessor.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/generator/InvocationContextProcessor.java
index c995a9330..5b4467ca5 100644
--- a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/generator/InvocationContextProcessor.java
+++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/generator/InvocationContextProcessor.java
@@ -17,6 +17,8 @@
package org.apache.servicecomb.swagger.invocation.generator;
+import java.lang.reflect.Type;
+
import org.apache.servicecomb.swagger.extend.parameter.InvocationContextParameter;
import org.apache.servicecomb.swagger.generator.core.CommonParameterTypeProcessor;
import org.apache.servicecomb.swagger.generator.core.OperationGenerator;
@@ -24,7 +26,7 @@
public class InvocationContextProcessor implements CommonParameterTypeProcessor {
@Override
- public Class<?> getParameterType() {
+ public Type getParameterType() {
return InvocationContext.class;
}
diff --git a/swagger/swagger-invocation/invocation-springmvc/pom.xml b/swagger/swagger-invocation/invocation-springmvc/pom.xml
index 6cd333dbc..bd9fc5b2b 100644
--- a/swagger/swagger-invocation/invocation-springmvc/pom.xml
+++ b/swagger/swagger-invocation/invocation-springmvc/pom.xml
@@ -32,6 +32,10 @@
<groupId>org.apache.servicecomb</groupId>
<artifactId>swagger-invocation-core</artifactId>
</dependency>
+ <dependency>
+ <groupId>com.google.inject</groupId>
+ <artifactId>guice</artifactId>
+ </dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
diff --git a/swagger/swagger-invocation/invocation-springmvc/src/main/java/org/apache/servicecomb/swagger/invocation/converter/SpringMultipartArrayConverter.java b/swagger/swagger-invocation/invocation-springmvc/src/main/java/org/apache/servicecomb/swagger/invocation/converter/SpringMultipartArrayConverter.java
new file mode 100644
index 000000000..cebbc293f
--- /dev/null
+++ b/swagger/swagger-invocation/invocation-springmvc/src/main/java/org/apache/servicecomb/swagger/invocation/converter/SpringMultipartArrayConverter.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.swagger.invocation.converter;
+
+import java.lang.reflect.Type;
+import java.util.List;
+
+import javax.servlet.http.Part;
+
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+import com.google.inject.util.Types;
+
+
+@Component
+public class SpringMultipartArrayConverter implements CustomizedConverter {
+
+ @Override
+ public Type getSrcType() {
+ return Types.newParameterizedType(List.class, Part.class);
+ }
+
+ @Override
+ public Type getTargetType() {
+ return MultipartFile[].class;
+ }
+
+ @Override
+ public Object convert(Object value) {
+ if (value == null) {
+ return null;
+ }
+ @SuppressWarnings("unchecked")
+ List<Part> partList = (List<Part>) value;
+ PartToMultipartFile[] partArray = new PartToMultipartFile[partList.size()];
+ for (int i = 0; i < partArray.length; i++) {
+ partArray[i] = new PartToMultipartFile(partList.get(i));
+ }
+ return partArray;
+ }
+}
diff --git a/swagger/swagger-invocation/invocation-springmvc/src/main/java/org/apache/servicecomb/swagger/invocation/converter/SpringMultipartListConverter.java b/swagger/swagger-invocation/invocation-springmvc/src/main/java/org/apache/servicecomb/swagger/invocation/converter/SpringMultipartListConverter.java
new file mode 100644
index 000000000..7ed7ba934
--- /dev/null
+++ b/swagger/swagger-invocation/invocation-springmvc/src/main/java/org/apache/servicecomb/swagger/invocation/converter/SpringMultipartListConverter.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.swagger.invocation.converter;
+
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.Part;
+
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+import com.google.inject.util.Types;
+
+@Component
+public class SpringMultipartListConverter implements CustomizedConverter {
+
+ @Override
+ public Type getSrcType() {
+ return Types.newParameterizedType(List.class, Part.class);
+ }
+
+ @Override
+ public Type getTargetType() {
+ return Types.newParameterizedType(List.class, MultipartFile.class);
+ }
+
+ @Override
+ public Object convert(Object value) {
+ if (value == null) {
+ return null;
+ }
+ @SuppressWarnings("unchecked")
+ List<Part> partList = (List<Part>) value;
+ List<PartToMultipartFile> fileList = new ArrayList<>();
+ partList.forEach(part -> {
+ fileList.add(new PartToMultipartFile(part));
+ });
+ return fileList;
+ }
+}
With regards,
Apache Git Services