This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git


The following commit(s) were added to refs/heads/master by this push:
     new eeacbec8c [SCB-2862]able to upload with List form parameters (#4235)
eeacbec8c is described below

commit eeacbec8c7ff659bc124638ad2de8ab2a7c9e03d
Author: liubao68 <[email protected]>
AuthorDate: Sun Feb 18 15:24:09 2024 +0800

    [SCB-2862]able to upload with List form parameters (#4235)
---
 .../rest/codec/param/FormProcessorCreator.java     |  8 +++++--
 .../common/rest/codec/query/QueryCodec.java        |  2 +-
 .../demo/springmvc/client/TestUploadSchema.java    | 22 +++++++++++++++++
 .../demo/springmvc/server/UploadSchema.java        | 15 ++++++++++++
 .../transport/rest/client/RestClientEncoder.java   | 28 +++++++++++++++-------
 5 files changed, 64 insertions(+), 11 deletions(-)

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 0f7bf6a63..4efedf3f1 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
@@ -120,8 +120,12 @@ public class FormProcessorCreator implements 
ParamValueProcessorCreator<RequestB
     MediaType file = parameter.getContent().get(SwaggerConst.FILE_MEDIA_TYPE);
     if (file != null) {
       Schema<?> schema = (Schema<?>) 
file.getSchema().getProperties().get(paramName);
-      return schema instanceof ArraySchema ||
-          ("string".equals(schema.getType()) && 
"binary".equals(schema.getFormat()));
+      if (schema instanceof ArraySchema) {
+        return "string".equals(schema.getItems().getType()) &&
+            "binary".equals(schema.getItems().getFormat());
+      } else {
+        return ("string".equals(schema.getType()) && 
"binary".equals(schema.getFormat()));
+      }
     }
     return false;
   }
diff --git 
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodec.java
 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodec.java
index 3282cc190..b9bfd1b71 100644
--- 
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodec.java
+++ 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodec.java
@@ -35,7 +35,7 @@ public interface QueryCodec extends Ordered {
     return URLEncoder.encode(value.toString(), StandardCharsets.UTF_8.name());
   }
 
-  // can not replaced by value.toString() because of date serialize
+  // can not be replaced by value.toString() because of date serialize
   static String convertToString(Object value) throws Exception {
     return 
RestObjectMapperFactory.getRestObjectMapper().convertToString(value);
   }
diff --git 
a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestUploadSchema.java
 
b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestUploadSchema.java
index 45b5d4c66..344b43144 100644
--- 
a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestUploadSchema.java
+++ 
b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestUploadSchema.java
@@ -60,6 +60,7 @@ public class TestUploadSchema implements CategorizedTestCase {
     testFileUploadMultiRpc();
     testUploadFileAndAttribute();
     testUploadFileRequestPartAttribute();
+    testUploadFileRequestPartAttributeList();
   }
 
   private void testServerStartupSuccess() {
@@ -141,4 +142,25 @@ public class TestUploadSchema implements 
CategorizedTestCase {
         new HttpEntity<>(map, headers), String.class);
     TestMgr.check("hi test", result);
   }
+
+  private void testUploadFileRequestPartAttributeList() throws Exception {
+    RestOperations template = RestTemplateBuilder.create();
+    MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
+    String message1 = "msg1";
+    String message2 = "msg2";
+    File file1 = File.createTempFile("file1", ".txt");
+    FileUtils.writeStringToFile(file1, "test1", StandardCharsets.UTF_8, false);
+    File file2 = File.createTempFile("file2", ".txt");
+    FileUtils.writeStringToFile(file2, "test2", StandardCharsets.UTF_8, false);
+
+    map.add("files", new FileSystemResource(file1));
+    map.add("files", new FileSystemResource(file2));
+    map.add("attributes", message1);
+    map.add("attributes", message2);
+    HttpHeaders headers = new HttpHeaders();
+    
headers.setContentType(org.springframework.http.MediaType.MULTIPART_FORM_DATA);
+    String result = 
template.postForObject("servicecomb://springmvc/upload/uploadFileRequestPartAttributeList",
+        new HttpEntity<>(map, headers), String.class);
+    TestMgr.check("test1test2msg1msg2", result);
+  }
 }
diff --git 
a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/UploadSchema.java
 
b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/UploadSchema.java
index 494a4d663..1a3a737d5 100644
--- 
a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/UploadSchema.java
+++ 
b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/UploadSchema.java
@@ -78,6 +78,21 @@ public class UploadSchema {
     }
   }
 
+  @PostMapping(path = "/uploadFileRequestPartAttributeList", produces = 
MediaType.TEXT_PLAIN_VALUE)
+  public String uploadFileRequestPartAttributeList(@RequestPart(name = 
"files") List<MultipartFile> files,
+      @RequestPart(name = "attributes") List<String> attributes) throws 
IOException {
+    StringBuilder result = new StringBuilder();
+    for (MultipartFile file : files) {
+      try (InputStream is = file.getInputStream()) {
+        result.append(IOUtils.toString(is, StandardCharsets.UTF_8));
+      }
+    }
+    for (String attribute : attributes) {
+      result.append(attribute);
+    }
+    return result.toString();
+  }
+
   @PostMapping(path = "/uploadFileAndAttribute", produces = 
MediaType.TEXT_PLAIN_VALUE)
   public String uploadFileAndAttribute(@RequestPart(name = "file") 
MultipartFile file,
       @RequestAttribute(name = "attribute") String attribute) throws 
IOException {
diff --git 
a/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestClientEncoder.java
 
b/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestClientEncoder.java
index 3bca8e89b..7a9b4330e 100644
--- 
a/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestClientEncoder.java
+++ 
b/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestClientEncoder.java
@@ -23,6 +23,7 @@ import static 
org.apache.servicecomb.transport.rest.client.RestClientExceptionCo
 
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
+import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
@@ -185,17 +186,28 @@ public class RestClientEncoder {
     protected Buffer genChunkedFormBuffer(Map<String, Object> formMap, String 
boundary) throws Exception {
       ByteBuf byteBuf = Unpooled.buffer(RestClientEncoder.FORM_BUFFER_SIZE);
       for (Entry<String, Object> entry : formMap.entrySet()) {
-        writeCharSequence(byteBuf, "\r\n--");
-        writeCharSequence(byteBuf, boundary);
-        writeCharSequence(byteBuf, "\r\nContent-Disposition: form-data; 
name=\"");
-        writeCharSequence(byteBuf, entry.getKey());
-        writeCharSequence(byteBuf, "\"\r\n\r\n");
-
-        String value = QueryCodec.convertToString(entry.getValue());
-        writeCharSequence(byteBuf, value);
+        Object content = entry.getValue();
+        if (content instanceof List<?>) {
+          for (Object item : ((List<?>) content)) {
+            writeFormData(byteBuf, boundary, entry.getKey(), item);
+          }
+        } else {
+          writeFormData(byteBuf, boundary, entry.getKey(), entry.getValue());
+        }
       }
       return Buffer.buffer(byteBuf);
     }
+
+    private void writeFormData(ByteBuf byteBuf, String boundary, String key, 
Object data) throws Exception {
+      writeCharSequence(byteBuf, "\r\n--");
+      writeCharSequence(byteBuf, boundary);
+      writeCharSequence(byteBuf, "\r\nContent-Disposition: form-data; 
name=\"");
+      writeCharSequence(byteBuf, key);
+      writeCharSequence(byteBuf, "\"\r\n\r\n");
+
+      String value = QueryCodec.convertToString(data);
+      writeCharSequence(byteBuf, value);
+    }
   }
 
   protected static void writeCharSequence(ByteBuf byteBuf, String value) {

Reply via email to