You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@servicecomb.apache.org by GitBox <gi...@apache.org> on 2017/12/22 03:15:59 UTC

[GitHub] WillemJiang closed pull request #434: [JAV-548] Pojo consumer upload

WillemJiang closed pull request #434: [JAV-548] Pojo consumer upload
URL: https://github.com/apache/incubator-servicecomb-java-chassis/pull/434
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/common/common-rest/src/main/java/io/servicecomb/common/rest/codec/param/RestClientRequestImpl.java b/common/common-rest/src/main/java/io/servicecomb/common/rest/codec/param/RestClientRequestImpl.java
index 19d6f4f51..2eda3634c 100644
--- a/common/common-rest/src/main/java/io/servicecomb/common/rest/codec/param/RestClientRequestImpl.java
+++ b/common/common-rest/src/main/java/io/servicecomb/common/rest/codec/param/RestClientRequestImpl.java
@@ -153,21 +153,22 @@ protected void doEndNormal() {
   }
 
   private void attachFiles(String boundary) {
-    Iterator<Part> uploadsIterator = uploads.values().iterator();
+    Iterator<Entry<String, Part>> uploadsIterator = uploads.entrySet().iterator();
     attachFile(boundary, uploadsIterator);
   }
 
-  private void attachFile(String boundary, Iterator<Part> uploadsIterator) {
+  private void attachFile(String boundary, Iterator<Entry<String, Part>> uploadsIterator) {
     if (!uploadsIterator.hasNext()) {
       request.write(boundaryEndInfo(boundary));
       request.end();
       return;
     }
 
-    // maybe it's a memory file, now we do not support this
-    // not easy to wrapping inputstream to readStream
-    Part part = uploadsIterator.next();
-    String name = part.getName();
+    Entry<String, Part> entry = uploadsIterator.next();
+    // do not use part.getName() to get parameter name
+    // because pojo consumer not easy to set name to part
+    String name = entry.getKey();
+    Part part = entry.getValue();
     String filename = part.getSubmittedFileName();
 
     InputStreamToReadStream fileStream = null;
diff --git a/demo/demo-signature/src/main/resources/META-INF/services/io.servicecomb.common.rest.filter.HttpServerFilter b/demo/demo-signature/src/main/resources/META-INF/services/io.servicecomb.common.rest.filter.HttpServerFilter
index ff16ac051..40126047c 100644
--- a/demo/demo-signature/src/main/resources/META-INF/services/io.servicecomb.common.rest.filter.HttpServerFilter
+++ b/demo/demo-signature/src/main/resources/META-INF/services/io.servicecomb.common.rest.filter.HttpServerFilter
@@ -15,21 +15,4 @@
 # limitations under the License.
 #
 
-#
-# 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.
-#
-
 io.servicecomb.demo.signature.ServerSignature
diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/io/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java b/demo/demo-springmvc/springmvc-client/src/main/java/io/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java
index 63ecca620..b2e59245b 100644
--- a/demo/demo-springmvc/springmvc-client/src/main/java/io/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java
+++ b/demo/demo-springmvc/springmvc-client/src/main/java/io/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java
@@ -17,14 +17,21 @@
 
 package io.servicecomb.demo.springmvc.client;
 
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
 
+import javax.servlet.http.Part;
+
 import org.apache.commons.io.FileUtils;
 import org.springframework.core.io.FileSystemResource;
+import org.springframework.core.io.PathResource;
+import org.springframework.core.io.Resource;
 import org.springframework.http.HttpEntity;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpMethod;
@@ -39,6 +46,8 @@
 import io.servicecomb.core.exception.CseException;
 import io.servicecomb.demo.CodeFirstRestTemplate;
 import io.servicecomb.demo.TestMgr;
+import io.servicecomb.foundation.common.part.FilePart;
+import io.servicecomb.provider.pojo.Invoker;
 import io.servicecomb.provider.pojo.RpcReference;
 import io.servicecomb.provider.springmvc.reference.CseHttpEntity;
 import io.servicecomb.serviceregistry.RegistryUtils;
@@ -46,6 +55,17 @@
 
 @Component
 public class CodeFirstRestTemplateSpringmvc extends CodeFirstRestTemplate {
+  interface UploadPartAndFile {
+    String fileUpload(Part file1, File file2);
+  }
+  interface UploadStreamAndResource {
+    String fileUpload(InputStream file1, Resource file2);
+  }
+
+  private UploadPartAndFile uploadPartAndFile = Invoker.createProxy("springmvc", "codeFirst", UploadPartAndFile.class);
+
+  private UploadStreamAndResource uploadStreamAndResource =
+      Invoker.createProxy("springmvc", "codeFirst", UploadStreamAndResource.class);
 
   @RpcReference(microserviceName = "springmvc", schemaId = "codeFirst")
   private CodeFirstSprigmvcIntf intf;
@@ -55,7 +75,7 @@ protected void testOnlyRest(RestTemplate template, String cseUrlPrefix) {
     try {
       testUpload(template, cseUrlPrefix);
     } catch (IOException e) {
-      e.printStackTrace();
+      throw new IllegalStateException(e);
     }
 
     super.testOnlyRest(template, cseUrlPrefix);
@@ -80,8 +100,16 @@ private void testUpload(RestTemplate template, String cseUrlPrefix) throws IOExc
     File someFile = File.createTempFile("upload2", ".txt");
     FileUtils.writeStringToFile(someFile, file2Content);
 
-    String templateResult = testRestTemplateUpload(template, cseUrlPrefix, file1, someFile);
-    TestMgr.check(file1Content + file2Content, templateResult);
+    String result = testRestTemplateUpload(template, cseUrlPrefix, file1, someFile);
+    TestMgr.check(file1Content + file2Content, result);
+
+    result = uploadPartAndFile.fileUpload(new FilePart(null, file1), someFile);
+    TestMgr.check(file1Content + file2Content, result);
+
+    result = uploadStreamAndResource
+        .fileUpload(new ByteArrayInputStream(file1Content.getBytes(StandardCharsets.UTF_8)),
+            new PathResource(someFile.getAbsolutePath()));
+    TestMgr.check(file1Content + file2Content, result);
   }
 
   private String testRestTemplateUpload(RestTemplate template, String cseUrlPrefix, File file1, File someFile) {
diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/io/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java b/demo/demo-springmvc/springmvc-server/src/main/java/io/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java
index 3fc76aab7..ff17d29de 100644
--- a/demo/demo-springmvc/springmvc-server/src/main/java/io/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java
+++ b/demo/demo-springmvc/springmvc-server/src/main/java/io/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java
@@ -24,6 +24,7 @@
 import java.util.Map;
 
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.Part;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Response.Status;
 
@@ -73,7 +74,7 @@
 @RestSchema(schemaId = "codeFirst")
 @RequestMapping(path = "/codeFirstSpringmvc", produces = MediaType.APPLICATION_JSON_VALUE)
 public class CodeFirstSpringmvc {
-  private String _fileUpload(MultipartFile file1, MultipartFile file2) {
+  private String _fileUpload(MultipartFile file1, Part file2) {
     try (InputStream is1 = file1.getInputStream(); InputStream is2 = file2.getInputStream()) {
       String content1 = IOUtils.toString(is1);
       String content2 = IOUtils.toString(is2);
@@ -85,7 +86,7 @@ private String _fileUpload(MultipartFile file1, MultipartFile file2) {
 
   @PostMapping(path = "/upload", produces = MediaType.TEXT_PLAIN_VALUE)
   public String fileUpload(@RequestPart(name = "file1") MultipartFile file1,
-      @RequestPart(name = "someFile") MultipartFile file2) {
+      @RequestPart(name = "someFile") Part file2) {
     return _fileUpload(file1, file2);
   }
 
diff --git a/demo/demo-springmvc/springmvc-server/src/main/resources/microservice.yaml b/demo/demo-springmvc/springmvc-server/src/main/resources/microservice.yaml
index 1b7e4e7b7..c5b61fbac 100644
--- a/demo/demo-springmvc/springmvc-server/src/main/resources/microservice.yaml
+++ b/demo/demo-springmvc/springmvc-server/src/main/resources/microservice.yaml
@@ -26,7 +26,7 @@ service_description:
     - path: /test2/testpath
       property:
         checksession: true
-cse.uploads.directory: .
+cse.uploads.directory: target
 cse:
   service:
     registry:
diff --git a/edge/edge-core/src/main/resources/META-INF/services/io.servicecomb.serviceregistry.discovery.DiscoveryFilter b/edge/edge-core/src/main/resources/META-INF/services/io.servicecomb.serviceregistry.discovery.DiscoveryFilter
index 75bbb9f03..aa61b93da 100644
--- a/edge/edge-core/src/main/resources/META-INF/services/io.servicecomb.serviceregistry.discovery.DiscoveryFilter
+++ b/edge/edge-core/src/main/resources/META-INF/services/io.servicecomb.serviceregistry.discovery.DiscoveryFilter
@@ -15,21 +15,4 @@
 # limitations under the License.
 #
 
-#
-# 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.
-#
-
 io.servicecomb.edge.core.OperationInstancesDiscoveryFilter
diff --git a/etc/code-templates.xml b/etc/code-templates.xml
index 66943fe36..dcb9150a4 100644
--- a/etc/code-templates.xml
+++ b/etc/code-templates.xml
@@ -20,13 +20,14 @@
   <template autoinsert="false" context="filecomment_context" deleted="false"
     description="Comment for created Java files" enabled="true"
     id="org.eclipse.jdt.ui.text.codetemplates.filecomment" name="filecomment">/*&#13;
- * Copyright 2017 Huawei Technologies Co., Ltd&#13;
+ * Licensed to the Apache Software Foundation (ASF) under one or more&#13;
+ * contributor license agreements.  See the NOTICE file distributed with&#13;
+ * this work for additional information regarding copyright ownership.&#13;
+ * The ASF licenses this file to You under the Apache License, Version 2.0&#13;
+ * (the "License"); you may not use this file except in compliance with&#13;
+ * the License.  You may obtain a copy of the License at&#13;
  *&#13;
- * Licensed under the Apache License, Version 2.0 (the "License");&#13;
- * you may not use this file except in compliance with the License.&#13;
- * You may obtain a copy of the License at&#13;
- *&#13;
- * http://www.apache.org/licenses/LICENSE-2.0&#13;
+ *     http://www.apache.org/licenses/LICENSE-2.0&#13;
  *&#13;
  * Unless required by applicable law or agreed to in writing, software&#13;
  * distributed under the License is distributed on an "AS IS" BASIS,&#13;
diff --git a/foundations/foundation-common/pom.xml b/foundations/foundation-common/pom.xml
index d5a360a60..298d7e202 100644
--- a/foundations/foundation-common/pom.xml
+++ b/foundations/foundation-common/pom.xml
@@ -71,5 +71,9 @@
 			<groupId>com.google.guava</groupId>
 			<artifactId>guava</artifactId>
 		</dependency>
+		<dependency>
+			<groupId>javax.servlet</groupId>
+			<artifactId>javax.servlet-api</artifactId>
+		</dependency>
 	</dependencies>
 </project>
diff --git a/foundations/foundation-vertx/src/main/java/io/servicecomb/foundation/vertx/part/AbstractPart.java b/foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/AbstractPart.java
similarity index 97%
rename from foundations/foundation-vertx/src/main/java/io/servicecomb/foundation/vertx/part/AbstractPart.java
rename to foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/AbstractPart.java
index f36fa0451..9a152f8c9 100644
--- a/foundations/foundation-vertx/src/main/java/io/servicecomb/foundation/vertx/part/AbstractPart.java
+++ b/foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/AbstractPart.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package io.servicecomb.foundation.vertx.part;
+package io.servicecomb.foundation.common.part;
 
 import java.io.IOException;
 import java.io.InputStream;
diff --git a/foundations/foundation-vertx/src/main/java/io/servicecomb/foundation/vertx/part/FilePart.java b/foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/FilePart.java
similarity index 97%
rename from foundations/foundation-vertx/src/main/java/io/servicecomb/foundation/vertx/part/FilePart.java
rename to foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/FilePart.java
index d71e970ea..aed6c6d6f 100644
--- a/foundations/foundation-vertx/src/main/java/io/servicecomb/foundation/vertx/part/FilePart.java
+++ b/foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/FilePart.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package io.servicecomb.foundation.vertx.part;
+package io.servicecomb.foundation.common.part;
 
 import java.io.File;
 import java.io.FileInputStream;
diff --git a/foundations/foundation-vertx/src/main/java/io/servicecomb/foundation/vertx/part/InputStreamPart.java b/foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/InputStreamPart.java
similarity index 95%
rename from foundations/foundation-vertx/src/main/java/io/servicecomb/foundation/vertx/part/InputStreamPart.java
rename to foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/InputStreamPart.java
index e7a3c1787..7efbfbcc2 100644
--- a/foundations/foundation-vertx/src/main/java/io/servicecomb/foundation/vertx/part/InputStreamPart.java
+++ b/foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/InputStreamPart.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package io.servicecomb.foundation.vertx.part;
+package io.servicecomb.foundation.common.part;
 
 import java.io.InputStream;
 
diff --git a/foundations/foundation-vertx/src/main/java/io/servicecomb/foundation/vertx/part/ResourcePart.java b/foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/ResourcePart.java
similarity index 96%
rename from foundations/foundation-vertx/src/main/java/io/servicecomb/foundation/vertx/part/ResourcePart.java
rename to foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/ResourcePart.java
index 5ba1599eb..22c53e47e 100644
--- a/foundations/foundation-vertx/src/main/java/io/servicecomb/foundation/vertx/part/ResourcePart.java
+++ b/foundations/foundation-common/src/main/java/io/servicecomb/foundation/common/part/ResourcePart.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package io.servicecomb.foundation.vertx.part;
+package io.servicecomb.foundation.common.part;
 
 import java.io.IOException;
 import java.io.InputStream;
diff --git a/foundations/foundation-common/src/test/java/io/servicecomb/foundation/common/part/TestAbstractPart.java b/foundations/foundation-common/src/test/java/io/servicecomb/foundation/common/part/TestAbstractPart.java
new file mode 100644
index 000000000..dcd5177d4
--- /dev/null
+++ b/foundations/foundation-common/src/test/java/io/servicecomb/foundation/common/part/TestAbstractPart.java
@@ -0,0 +1,116 @@
+/*
+ * 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 io.servicecomb.foundation.common.part;
+
+import java.io.IOException;
+
+import javax.ws.rs.core.MediaType;
+
+import org.hamcrest.Matchers;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class TestAbstractPart {
+  AbstractPart part = new AbstractPart();
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  private void initExpectedException() {
+    expectedException.expect(Error.class);
+    expectedException.expectMessage(Matchers.is("not supported method"));
+  }
+
+  @Test
+  public void getInputStream() throws IOException {
+    initExpectedException();
+
+    part.getInputStream();
+  }
+
+  @Test
+  public void getContentType() throws IOException {
+    Assert.assertEquals(MediaType.MULTIPART_FORM_DATA, part.getContentType());
+
+    String contentType = "abc";
+    part.contentType(contentType);
+    Assert.assertEquals(contentType, part.getContentType());
+  }
+
+  @Test
+  public void getName() throws IOException {
+    Assert.assertNull(part.getName());
+
+    String name = "abc";
+    part.name = name;
+    Assert.assertEquals(name, part.getName());
+  }
+
+  @Test
+  public void getSubmittedFileName() throws IOException {
+    Assert.assertNull(part.getSubmittedFileName());
+
+    String submittedFileName = "abc";
+    part.submittedFileName = submittedFileName;
+    Assert.assertEquals(submittedFileName, part.getSubmittedFileName());
+  }
+
+  @Test
+  public void getSize() {
+    initExpectedException();
+
+    part.getSize();
+  }
+
+  @Test
+  public void write() throws IOException {
+    initExpectedException();
+
+    part.write("file");
+  }
+
+  @Test
+  public void delete() throws IOException {
+    initExpectedException();
+
+    part.delete();
+  }
+
+  @Test
+  public void getHeader() {
+    initExpectedException();
+
+    part.getHeader("header");
+  }
+
+  @Test
+  public void getHeaders() {
+    initExpectedException();
+
+    part.getHeaders("header");
+  }
+
+  @Test
+  public void getHeaderNames() {
+    initExpectedException();
+
+    part.getHeaderNames();
+  }
+}
diff --git a/foundations/foundation-common/src/test/java/io/servicecomb/foundation/common/part/TestFilePart.java b/foundations/foundation-common/src/test/java/io/servicecomb/foundation/common/part/TestFilePart.java
new file mode 100644
index 000000000..5a50eb213
--- /dev/null
+++ b/foundations/foundation-common/src/test/java/io/servicecomb/foundation/common/part/TestFilePart.java
@@ -0,0 +1,76 @@
+/*
+ * 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 io.servicecomb.foundation.common.part;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class TestFilePart {
+  static File file = new File("testFilePart.txt");
+
+  static String content = "testFilePart content";
+
+  String name = "paramName";
+
+  FilePart part = new FilePart(name, file.getAbsolutePath());
+
+  @BeforeClass
+  public static void setup() throws IOException {
+    file.delete();
+    FileUtils.write(file, content);
+  }
+
+  @AfterClass
+  public static void teardown() {
+    file.delete();
+  }
+
+  @Test
+  public void getName() {
+    Assert.assertEquals(name, part.getName());
+  }
+
+  @Test
+  public void getInputStream() throws IOException {
+    try (InputStream is = part.getInputStream()) {
+      Assert.assertEquals(content, IOUtils.toString(is));
+    }
+  }
+
+  @Test
+  public void getSize() {
+    Assert.assertEquals(content.length(), part.getSize());
+  }
+
+  @Test
+  public void write() throws IOException {
+    File destFile = new File("testFilePartCopy.txt");
+
+    part.write(destFile.getPath());
+    Assert.assertEquals(content, FileUtils.readFileToString(destFile));
+    destFile.delete();
+  }
+}
diff --git a/foundations/foundation-common/src/test/java/io/servicecomb/foundation/common/part/TestInputStreamPart.java b/foundations/foundation-common/src/test/java/io/servicecomb/foundation/common/part/TestInputStreamPart.java
new file mode 100644
index 000000000..569acda9a
--- /dev/null
+++ b/foundations/foundation-common/src/test/java/io/servicecomb/foundation/common/part/TestInputStreamPart.java
@@ -0,0 +1,49 @@
+/*
+ * 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 io.servicecomb.foundation.common.part;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestInputStreamPart {
+  String name = "paramName";
+
+  byte[] bytes = new byte[] {1, 2, 3};
+
+  InputStream is = new ByteArrayInputStream(bytes);
+
+  InputStreamPart part = new InputStreamPart(name, is);
+
+  @Test
+  public void getName() {
+    Assert.assertEquals(name, part.getName());
+  }
+
+  @Test
+  public void test() throws IOException {
+    try (InputStream is = part.getInputStream()) {
+      byte[] content = IOUtils.toByteArray(is);
+      Assert.assertArrayEquals(bytes, content);
+    }
+  }
+}
diff --git a/foundations/foundation-common/src/test/java/io/servicecomb/foundation/common/part/TestResourcePart.java b/foundations/foundation-common/src/test/java/io/servicecomb/foundation/common/part/TestResourcePart.java
new file mode 100644
index 000000000..ba2d003cc
--- /dev/null
+++ b/foundations/foundation-common/src/test/java/io/servicecomb/foundation/common/part/TestResourcePart.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 io.servicecomb.foundation.common.part;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.core.io.ByteArrayResource;
+import org.springframework.core.io.Resource;
+
+public class TestResourcePart {
+  String name = "paramName";
+
+  byte[] bytes = new byte[] {1, 2, 3};
+
+  Resource resource = new ByteArrayResource(bytes);
+
+  ResourcePart part = new ResourcePart(name, resource);
+
+  @Test
+  public void getName() {
+    Assert.assertEquals(name, part.getName());
+  }
+
+  @Test
+  public void getInputStream() throws IOException {
+    try (InputStream is = part.getInputStream()) {
+      byte[] content = IOUtils.toByteArray(is);
+      Assert.assertArrayEquals(bytes, content);
+    }
+  }
+}
diff --git a/foundations/foundation-common/src/test/resources/META-INF/services/io.servicecomb.foundation.common.utils.SPIServiceDef b/foundations/foundation-common/src/test/resources/META-INF/services/io.servicecomb.foundation.common.utils.SPIServiceDef
index 777ab262f..59b7cd53f 100644
--- a/foundations/foundation-common/src/test/resources/META-INF/services/io.servicecomb.foundation.common.utils.SPIServiceDef
+++ b/foundations/foundation-common/src/test/resources/META-INF/services/io.servicecomb.foundation.common.utils.SPIServiceDef
@@ -15,37 +15,5 @@
 # limitations under the License.
 #
 
-#
-# 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.
-#
-
-#
-# Copyright 2017 Huawei Technologies Co., Ltd
-#
-# Licensed 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.
-#
 
-io.servicecomb.foundation.common.utils.SPIServiceDefImpl
+io.servicecomb.foundation.common.utils.SPIServiceDefImpl
\ No newline at end of file
diff --git a/foundations/foundation-config-cc/src/main/resources/META-INF/services/io.servicecomb.config.spi.ConfigCenterConfigurationSource b/foundations/foundation-config-cc/src/main/resources/META-INF/services/io.servicecomb.config.spi.ConfigCenterConfigurationSource
index e1355f564..55043eb24 100644
--- a/foundations/foundation-config-cc/src/main/resources/META-INF/services/io.servicecomb.config.spi.ConfigCenterConfigurationSource
+++ b/foundations/foundation-config-cc/src/main/resources/META-INF/services/io.servicecomb.config.spi.ConfigCenterConfigurationSource
@@ -15,37 +15,4 @@
 # limitations under the License.
 #
 
-#
-# 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.
-#
-
-#
-# Copyright 2017 Huawei Technologies Co., Ltd
-#
-# Licensed 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.
-#
-
-io.servicecomb.config.archaius.sources.ConfigCenterConfigurationSourceImpl
+io.servicecomb.config.archaius.sources.ConfigCenterConfigurationSourceImpl
\ No newline at end of file
diff --git a/foundations/foundation-config/src/test/resources/META-INF/services/io.servicecomb.config.spi.ConfigCenterConfigurationSource b/foundations/foundation-config/src/test/resources/META-INF/services/io.servicecomb.config.spi.ConfigCenterConfigurationSource
index af0fbecbb..dc9585f14 100644
--- a/foundations/foundation-config/src/test/resources/META-INF/services/io.servicecomb.config.spi.ConfigCenterConfigurationSource
+++ b/foundations/foundation-config/src/test/resources/META-INF/services/io.servicecomb.config.spi.ConfigCenterConfigurationSource
@@ -15,37 +15,5 @@
 # limitations under the License.
 #
 
-#
-# 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.
-#
-
-#
-# Copyright 2017 Huawei Technologies Co., Ltd
-#
-# Licensed 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.
-#
 
-io.servicecomb.config.MapBasedConfigurationSource
+io.servicecomb.config.MapBasedConfigurationSource
\ No newline at end of file
diff --git a/foundations/foundation-vertx/pom.xml b/foundations/foundation-vertx/pom.xml
index 0728d9d70..cc9b6cc9e 100644
--- a/foundations/foundation-vertx/pom.xml
+++ b/foundations/foundation-vertx/pom.xml
@@ -42,10 +42,6 @@
       <groupId>io.servicecomb</groupId>
       <artifactId>foundation-common</artifactId>
     </dependency>
-    <dependency>
-      <groupId>javax.servlet</groupId>
-      <artifactId>javax.servlet-api</artifactId>
-    </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-log4j12</artifactId>
diff --git a/foundations/foundation-vertx/src/main/java/io/servicecomb/foundation/vertx/http/VertxServerRequestToHttpServletRequest.java b/foundations/foundation-vertx/src/main/java/io/servicecomb/foundation/vertx/http/VertxServerRequestToHttpServletRequest.java
index 57a79c7f7..7bba5bde9 100644
--- a/foundations/foundation-vertx/src/main/java/io/servicecomb/foundation/vertx/http/VertxServerRequestToHttpServletRequest.java
+++ b/foundations/foundation-vertx/src/main/java/io/servicecomb/foundation/vertx/http/VertxServerRequestToHttpServletRequest.java
@@ -36,7 +36,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import io.servicecomb.foundation.vertx.part.FilePart;
+import io.servicecomb.foundation.common.part.FilePart;
 import io.servicecomb.foundation.vertx.stream.BufferInputStream;
 import io.vertx.core.MultiMap;
 import io.vertx.core.buffer.Buffer;
@@ -47,6 +47,7 @@
 // wrap vertx http request to Servlet http request
 public class VertxServerRequestToHttpServletRequest extends AbstractHttpServletRequest {
   private static final Logger LOGGER = LoggerFactory.getLogger(VertxServerRequestToHttpServletRequest.class);
+
   private static final EmptyAsyncContext EMPTY_ASYNC_CONTEXT = new EmptyAsyncContext();
 
   private RoutingContext context;
diff --git a/integration-tests/springmvc-tests/pom.xml b/integration-tests/springmvc-tests/pom.xml
index 692554f2c..f37644611 100644
--- a/integration-tests/springmvc-tests/pom.xml
+++ b/integration-tests/springmvc-tests/pom.xml
@@ -38,10 +38,6 @@
         </exclusion>
       </exclusions>
     </dependency>
-    <dependency>
-      <groupId>io.servicecomb</groupId>
-      <artifactId>provider-rest-common</artifactId>
-    </dependency>
     <dependency>
       <groupId>io.servicecomb</groupId>
       <artifactId>provider-springmvc</artifactId>
diff --git a/integration-tests/springmvc-tests/src/test/java/io/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcBase.java b/integration-tests/springmvc-tests/src/test/java/io/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcBase.java
index 6f73b334f..35d6266eb 100644
--- a/integration-tests/springmvc-tests/src/test/java/io/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcBase.java
+++ b/integration-tests/springmvc-tests/src/test/java/io/servicecomb/demo/springmvc/tests/endpoints/CodeFirstSpringmvcBase.java
@@ -18,6 +18,7 @@
 package io.servicecomb.demo.springmvc.tests.endpoints;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
@@ -76,7 +77,9 @@ public String textPlain(String body) {
 
   public String fileUpload(MultipartFile file1, MultipartFile file2, String name) {
     try {
-      return IOUtils.toString(file1.getInputStream()) + IOUtils.toString(file2.getInputStream()) + name;
+      return IOUtils.toString(file1.getBytes(), StandardCharsets.UTF_8.name())
+          + IOUtils.toString(file2.getBytes(), StandardCharsets.UTF_8.name())
+          + name;
     } catch (IOException e) {
       throw new IllegalArgumentException(e);
     }
diff --git a/providers/provider-springmvc/src/main/java/io/servicecomb/provider/springmvc/reference/CommonToHttpServletRequest.java b/providers/provider-springmvc/src/main/java/io/servicecomb/provider/springmvc/reference/CommonToHttpServletRequest.java
index c2f36faad..959398351 100644
--- a/providers/provider-springmvc/src/main/java/io/servicecomb/provider/springmvc/reference/CommonToHttpServletRequest.java
+++ b/providers/provider-springmvc/src/main/java/io/servicecomb/provider/springmvc/reference/CommonToHttpServletRequest.java
@@ -38,10 +38,10 @@
 import org.springframework.core.io.Resource;
 
 import io.servicecomb.common.rest.RestConst;
+import io.servicecomb.foundation.common.part.FilePart;
+import io.servicecomb.foundation.common.part.InputStreamPart;
+import io.servicecomb.foundation.common.part.ResourcePart;
 import io.servicecomb.foundation.vertx.http.AbstractHttpServletRequest;
-import io.servicecomb.foundation.vertx.part.FilePart;
-import io.servicecomb.foundation.vertx.part.InputStreamPart;
-import io.servicecomb.foundation.vertx.part.ResourcePart;
 
 // restTemplate convert parameters to invocation args.
 public class CommonToHttpServletRequest extends AbstractHttpServletRequest {
diff --git a/swagger/swagger-generator/generator-core/src/main/java/io/servicecomb/swagger/extend/ModelResolverExt.java b/swagger/swagger-generator/generator-core/src/main/java/io/servicecomb/swagger/extend/ModelResolverExt.java
index 3dfb2273c..0044a8de0 100644
--- a/swagger/swagger-generator/generator-core/src/main/java/io/servicecomb/swagger/extend/ModelResolverExt.java
+++ b/swagger/swagger-generator/generator-core/src/main/java/io/servicecomb/swagger/extend/ModelResolverExt.java
@@ -35,6 +35,7 @@
 import io.servicecomb.swagger.extend.property.creator.ByteArrayPropertyCreator;
 import io.servicecomb.swagger.extend.property.creator.BytePropertyCreator;
 import io.servicecomb.swagger.extend.property.creator.InputStreamPropertyCreator;
+import io.servicecomb.swagger.extend.property.creator.PartPropertyCreator;
 import io.servicecomb.swagger.extend.property.creator.PropertyCreator;
 import io.servicecomb.swagger.extend.property.creator.ShortPropertyCreator;
 import io.swagger.converter.ModelConverter;
@@ -58,6 +59,7 @@ public ModelResolverExt() {
     addPropertyCreator(new ShortPropertyCreator());
     addPropertyCreator(new ByteArrayPropertyCreator());
     addPropertyCreator(new InputStreamPropertyCreator());
+    addPropertyCreator(new PartPropertyCreator());
     loadPropertyCreators();
   }
 
diff --git a/swagger/swagger-generator/generator-core/src/main/java/io/servicecomb/swagger/extend/property/creator/PartPropertyCreator.java b/swagger/swagger-generator/generator-core/src/main/java/io/servicecomb/swagger/extend/property/creator/PartPropertyCreator.java
new file mode 100644
index 000000000..7d8fb2059
--- /dev/null
+++ b/swagger/swagger-generator/generator-core/src/main/java/io/servicecomb/swagger/extend/property/creator/PartPropertyCreator.java
@@ -0,0 +1,37 @@
+/*
+ * 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 io.servicecomb.swagger.extend.property.creator;
+
+import javax.servlet.http.Part;
+
+import io.swagger.models.properties.FileProperty;
+import io.swagger.models.properties.Property;
+
+public class PartPropertyCreator implements PropertyCreator {
+  private final Class<?>[] classes = {Part.class};
+
+  @Override
+  public Property createProperty() {
+    return new FileProperty();
+  }
+
+  @Override
+  public Class<?>[] classes() {
+    return classes;
+  }
+}
diff --git a/swagger/swagger-generator/generator-core/src/test/java/io/servicecomb/swagger/extend/property/creator/TestPartPropertyCreator.java b/swagger/swagger-generator/generator-core/src/test/java/io/servicecomb/swagger/extend/property/creator/TestPartPropertyCreator.java
new file mode 100644
index 000000000..4e8c8e57e
--- /dev/null
+++ b/swagger/swagger-generator/generator-core/src/test/java/io/servicecomb/swagger/extend/property/creator/TestPartPropertyCreator.java
@@ -0,0 +1,42 @@
+/*
+ * 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 io.servicecomb.swagger.extend.property.creator;
+
+import javax.servlet.http.Part;
+
+import org.hamcrest.Matchers;
+import org.junit.Assert;
+import org.junit.Test;
+
+import io.swagger.models.properties.FileProperty;
+
+
+public class TestPartPropertyCreator {
+  PartPropertyCreator creator = new PartPropertyCreator();
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void classes() {
+    Assert.assertThat(creator.classes(), Matchers.arrayContaining(Part.class));
+  }
+
+  @Test
+  public void createProperty() {
+    Assert.assertThat(creator.createProperty(), Matchers.instanceOf(FileProperty.class));
+  }
+}
diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/io/servicecomb/swagger/invocation/converter/impl/part/FileToPartConverter.java b/swagger/swagger-invocation/invocation-core/src/main/java/io/servicecomb/swagger/invocation/converter/impl/part/FileToPartConverter.java
new file mode 100644
index 000000000..d6a7c4a77
--- /dev/null
+++ b/swagger/swagger-invocation/invocation-core/src/main/java/io/servicecomb/swagger/invocation/converter/impl/part/FileToPartConverter.java
@@ -0,0 +1,48 @@
+/*
+ * 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 io.servicecomb.swagger.invocation.converter.impl.part;
+
+import java.io.File;
+import java.lang.reflect.Type;
+
+import javax.servlet.http.Part;
+
+import org.springframework.stereotype.Component;
+
+import io.servicecomb.foundation.common.part.FilePart;
+import io.servicecomb.swagger.invocation.converter.CustomizedConverter;
+
+@Component
+public class FileToPartConverter implements CustomizedConverter {
+  @Override
+  public Type getSrcType() {
+    return File.class;
+  }
+
+  @Override
+  public Type getTargetType() {
+    return Part.class;
+  }
+
+  @Override
+  public Object convert(Object value) {
+    // not set name, because not easy to get parameter name in this place
+    // io.servicecomb.common.rest.codec.param.RestClientRequestImpl not depend on the name
+    return new FilePart(null, (File) value);
+  }
+}
diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/io/servicecomb/swagger/invocation/converter/impl/part/InputStreamToPartConverter.java b/swagger/swagger-invocation/invocation-core/src/main/java/io/servicecomb/swagger/invocation/converter/impl/part/InputStreamToPartConverter.java
new file mode 100644
index 000000000..90aeded65
--- /dev/null
+++ b/swagger/swagger-invocation/invocation-core/src/main/java/io/servicecomb/swagger/invocation/converter/impl/part/InputStreamToPartConverter.java
@@ -0,0 +1,48 @@
+/*
+ * 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 io.servicecomb.swagger.invocation.converter.impl.part;
+
+import java.io.InputStream;
+import java.lang.reflect.Type;
+
+import javax.servlet.http.Part;
+
+import org.springframework.stereotype.Component;
+
+import io.servicecomb.foundation.common.part.InputStreamPart;
+import io.servicecomb.swagger.invocation.converter.CustomizedConverter;
+
+@Component
+public class InputStreamToPartConverter implements CustomizedConverter {
+  @Override
+  public Type getSrcType() {
+    return InputStream.class;
+  }
+
+  @Override
+  public Type getTargetType() {
+    return Part.class;
+  }
+
+  @Override
+  public Object convert(Object value) {
+    // not set name, because not easy to get parameter name in this place
+    // io.servicecomb.common.rest.codec.param.RestClientRequestImpl not depend on the name
+    return new InputStreamPart(null, (InputStream) value);
+  }
+}
diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/io/servicecomb/swagger/invocation/converter/impl/part/ResourceToPartConverter.java b/swagger/swagger-invocation/invocation-core/src/main/java/io/servicecomb/swagger/invocation/converter/impl/part/ResourceToPartConverter.java
new file mode 100644
index 000000000..273e1a5b4
--- /dev/null
+++ b/swagger/swagger-invocation/invocation-core/src/main/java/io/servicecomb/swagger/invocation/converter/impl/part/ResourceToPartConverter.java
@@ -0,0 +1,48 @@
+/*
+ * 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 io.servicecomb.swagger.invocation.converter.impl.part;
+
+import java.lang.reflect.Type;
+
+import javax.servlet.http.Part;
+
+import org.springframework.core.io.Resource;
+import org.springframework.stereotype.Component;
+
+import io.servicecomb.foundation.common.part.ResourcePart;
+import io.servicecomb.swagger.invocation.converter.CustomizedConverter;
+
+@Component
+public class ResourceToPartConverter implements CustomizedConverter {
+  @Override
+  public Type getSrcType() {
+    return Resource.class;
+  }
+
+  @Override
+  public Type getTargetType() {
+    return Part.class;
+  }
+
+  @Override
+  public Object convert(Object value) {
+    // not set name, because not easy to get parameter name in this place
+    // io.servicecomb.common.rest.codec.param.RestClientRequestImpl not depend on the name
+    return new ResourcePart(null, (Resource) value);
+  }
+}
diff --git a/swagger/swagger-invocation/invocation-core/src/test/java/io/servicecomb/swagger/invocation/converter/impl/part/TestFileToPartConverter.java b/swagger/swagger-invocation/invocation-core/src/test/java/io/servicecomb/swagger/invocation/converter/impl/part/TestFileToPartConverter.java
new file mode 100644
index 000000000..934d24034
--- /dev/null
+++ b/swagger/swagger-invocation/invocation-core/src/test/java/io/servicecomb/swagger/invocation/converter/impl/part/TestFileToPartConverter.java
@@ -0,0 +1,47 @@
+/*
+ * 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 io.servicecomb.swagger.invocation.converter.impl.part;
+
+import java.io.File;
+
+import javax.servlet.http.Part;
+
+import org.hamcrest.Matchers;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestFileToPartConverter {
+  FileToPartConverter converter = new FileToPartConverter();
+
+  @Test
+  public void getSrcType() {
+    Assert.assertEquals(File.class.getName(), converter.getSrcType().getTypeName());
+  }
+
+  @Test
+  public void getTargetType() {
+    Assert.assertEquals(Part.class.getName(), converter.getTargetType().getTypeName());
+  }
+
+  @Test
+  public void convert() {
+    File file = new File("abc");
+    Object part = converter.convert(file);
+    Assert.assertThat(part, Matchers.instanceOf(Part.class));
+  }
+}
diff --git a/swagger/swagger-invocation/invocation-core/src/test/java/io/servicecomb/swagger/invocation/converter/impl/part/TestInputStreamToPartConverter.java b/swagger/swagger-invocation/invocation-core/src/test/java/io/servicecomb/swagger/invocation/converter/impl/part/TestInputStreamToPartConverter.java
new file mode 100644
index 000000000..b288c12e9
--- /dev/null
+++ b/swagger/swagger-invocation/invocation-core/src/test/java/io/servicecomb/swagger/invocation/converter/impl/part/TestInputStreamToPartConverter.java
@@ -0,0 +1,47 @@
+/*
+ * 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 io.servicecomb.swagger.invocation.converter.impl.part;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import javax.servlet.http.Part;
+
+import org.hamcrest.Matchers;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestInputStreamToPartConverter {
+  InputStreamToPartConverter converter = new InputStreamToPartConverter();
+
+  @Test
+  public void getSrcType() {
+    Assert.assertEquals(InputStream.class.getName(), converter.getSrcType().getTypeName());
+  }
+
+  @Test
+  public void getTargetType() {
+    Assert.assertEquals(Part.class.getName(), converter.getTargetType().getTypeName());
+  }
+
+  @Test
+  public void convert() {
+    Object part = converter.convert(new ByteArrayInputStream(new byte[] {}));
+    Assert.assertThat(part, Matchers.instanceOf(Part.class));
+  }
+}
diff --git a/swagger/swagger-invocation/invocation-core/src/test/java/io/servicecomb/swagger/invocation/converter/impl/part/TestResourceToPartConverter.java b/swagger/swagger-invocation/invocation-core/src/test/java/io/servicecomb/swagger/invocation/converter/impl/part/TestResourceToPartConverter.java
new file mode 100644
index 000000000..8aa9c8b00
--- /dev/null
+++ b/swagger/swagger-invocation/invocation-core/src/test/java/io/servicecomb/swagger/invocation/converter/impl/part/TestResourceToPartConverter.java
@@ -0,0 +1,48 @@
+/*
+ * 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 io.servicecomb.swagger.invocation.converter.impl.part;
+
+import java.io.ByteArrayInputStream;
+
+import javax.servlet.http.Part;
+
+import org.hamcrest.Matchers;
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.core.io.InputStreamResource;
+import org.springframework.core.io.Resource;
+
+public class TestResourceToPartConverter {
+  ResourceToPartConverter converter = new ResourceToPartConverter();
+
+  @Test
+  public void getSrcType() {
+    Assert.assertEquals(Resource.class.getName(), converter.getSrcType().getTypeName());
+  }
+
+  @Test
+  public void getTargetType() {
+    Assert.assertEquals(Part.class.getName(), converter.getTargetType().getTypeName());
+  }
+
+  @Test
+  public void convert() {
+    Object part = converter.convert(new InputStreamResource(new ByteArrayInputStream(new byte[] {})));
+    Assert.assertThat(part, Matchers.instanceOf(Part.class));
+  }
+}
diff --git a/swagger/swagger-invocation/invocation-springmvc/src/main/java/io/servicecomb/swagger/invocation/converter/PartToMultipartFile.java b/swagger/swagger-invocation/invocation-springmvc/src/main/java/io/servicecomb/swagger/invocation/converter/PartToMultipartFile.java
new file mode 100644
index 000000000..8e83d7c03
--- /dev/null
+++ b/swagger/swagger-invocation/invocation-springmvc/src/main/java/io/servicecomb/swagger/invocation/converter/PartToMultipartFile.java
@@ -0,0 +1,77 @@
+/*
+ * 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 io.servicecomb.swagger.invocation.converter;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.servlet.http.Part;
+
+import org.apache.commons.io.IOUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+public class PartToMultipartFile implements MultipartFile {
+  private Part part;
+
+  public PartToMultipartFile(Part part) {
+    this.part = part;
+  }
+
+  @Override
+  public String getName() {
+    return part.getName();
+  }
+
+  @Override
+  public String getOriginalFilename() {
+    return part.getSubmittedFileName();
+  }
+
+  @Override
+  public String getContentType() {
+    return part.getContentType();
+  }
+
+  @Override
+  public boolean isEmpty() {
+    return part.getSize() == 0;
+  }
+
+  @Override
+  public long getSize() {
+    return part.getSize();
+  }
+
+  @Override
+  public byte[] getBytes() throws IOException {
+    try (InputStream is = getInputStream()) {
+      return IOUtils.toByteArray(is);
+    }
+  }
+
+  @Override
+  public InputStream getInputStream() throws IOException {
+    return part.getInputStream();
+  }
+
+  @Override
+  public void transferTo(File dest) throws IOException, IllegalStateException {
+    part.write(dest.getPath());
+  }
+}
diff --git a/swagger/swagger-invocation/invocation-springmvc/src/main/java/io/servicecomb/swagger/invocation/converter/SpringMultipartConverter.java b/swagger/swagger-invocation/invocation-springmvc/src/main/java/io/servicecomb/swagger/invocation/converter/SpringMultipartConverter.java
index 5e8e0e065..d4618a59f 100644
--- a/swagger/swagger-invocation/invocation-springmvc/src/main/java/io/servicecomb/swagger/invocation/converter/SpringMultipartConverter.java
+++ b/swagger/swagger-invocation/invocation-springmvc/src/main/java/io/servicecomb/swagger/invocation/converter/SpringMultipartConverter.java
@@ -17,14 +17,10 @@
 
 package io.servicecomb.swagger.invocation.converter;
 
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
 import java.lang.reflect.Type;
 
 import javax.servlet.http.Part;
 
-import org.apache.commons.io.IOUtils;
 import org.springframework.stereotype.Component;
 import org.springframework.web.multipart.MultipartFile;
 
@@ -46,47 +42,6 @@ public Object convert(Object value) {
       return null;
     }
 
-    Part part = (Part) value;
-    return new MultipartFile() {
-      @Override
-      public String getName() {
-        return part.getName();
-      }
-
-      @Override
-      public String getOriginalFilename() {
-        return part.getSubmittedFileName();
-      }
-
-      @Override
-      public String getContentType() {
-        return part.getContentType();
-      }
-
-      @Override
-      public boolean isEmpty() {
-        return part.getSize() == 0;
-      }
-
-      @Override
-      public long getSize() {
-        return part.getSize();
-      }
-
-      @Override
-      public byte[] getBytes() throws IOException {
-        return IOUtils.toByteArray(part.getInputStream());
-      }
-
-      @Override
-      public InputStream getInputStream() throws IOException {
-        return part.getInputStream();
-      }
-
-      @Override
-      public void transferTo(File dest) throws IOException, IllegalStateException {
-        part.write(dest.getPath());
-      }
-    };
+    return new PartToMultipartFile((Part) value);
   }
 }
diff --git a/swagger/swagger-invocation/invocation-springmvc/src/test/java/io/servicecomb/swagger/invocation/converter/TestPartToMultipartFile.java b/swagger/swagger-invocation/invocation-springmvc/src/test/java/io/servicecomb/swagger/invocation/converter/TestPartToMultipartFile.java
new file mode 100644
index 000000000..dc15aaad1
--- /dev/null
+++ b/swagger/swagger-invocation/invocation-springmvc/src/test/java/io/servicecomb/swagger/invocation/converter/TestPartToMultipartFile.java
@@ -0,0 +1,186 @@
+/*
+ * 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 io.servicecomb.swagger.invocation.converter;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+
+import javax.servlet.http.Part;
+import javax.xml.ws.Holder;
+
+import org.hamcrest.Matchers;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import mockit.Expectations;
+import mockit.Mock;
+import mockit.MockUp;
+import mockit.Mocked;
+
+public class TestPartToMultipartFile {
+  @Mocked
+  Part part;
+
+  PartToMultipartFile multipartFile;
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Before
+  public void setup() {
+    multipartFile = new PartToMultipartFile(part);
+  }
+
+  @Test
+  public void getName() {
+    String name = "paramName";
+    new Expectations() {
+      {
+        part.getName();
+        result = name;
+      }
+    };
+
+    Assert.assertEquals(name, multipartFile.getName());
+  }
+
+  @Test
+  public void getOriginalFilename() {
+    String submittedFileName = "fileName";
+    new Expectations() {
+      {
+        part.getSubmittedFileName();
+        result = submittedFileName;
+      }
+    };
+
+    Assert.assertEquals(submittedFileName, multipartFile.getOriginalFilename());
+  }
+
+  @Test
+  public void getContentType() {
+    String contentType = "json";
+    new Expectations() {
+      {
+        part.getContentType();
+        result = contentType;
+      }
+    };
+
+    Assert.assertEquals(contentType, multipartFile.getContentType());
+  }
+
+  @Test
+  public void isEmptyTrue() {
+    new Expectations() {
+      {
+        part.getSize();
+        result = 0;
+      }
+    };
+
+    Assert.assertTrue(multipartFile.isEmpty());
+  }
+
+  @Test
+  public void isEmptyFalse() {
+    new Expectations() {
+      {
+        part.getSize();
+        result = 1;
+      }
+    };
+
+    Assert.assertFalse(multipartFile.isEmpty());
+  }
+
+  @Test
+  public void getSize() {
+    long size = 10;
+    new Expectations() {
+      {
+        part.getSize();
+        result = size;
+      }
+    };
+
+    Assert.assertEquals(size, multipartFile.getSize());
+  }
+
+  class ByteArrayInputStreamForTest extends ByteArrayInputStream {
+    boolean closed;
+
+    public ByteArrayInputStreamForTest(byte[] buf) {
+      super(buf);
+    }
+
+    @Override
+    public void close() throws IOException {
+      closed = true;
+    }
+  }
+
+  @Test
+  public void getBytes_normal() throws IOException {
+    byte[] bytes = new byte[] {1, 2, 3};
+    ByteArrayInputStreamForTest is = new ByteArrayInputStreamForTest(bytes);
+    new Expectations() {
+      {
+        part.getInputStream();
+        result = is;
+      }
+    };
+
+    Assert.assertArrayEquals(bytes, multipartFile.getBytes());
+    Assert.assertTrue(is.closed);
+  }
+
+  @Test
+  public void getBytes_exception() throws IOException {
+    new Expectations() {
+      {
+        part.getInputStream();
+        result = new IOException("open stream failed");
+      }
+    };
+
+    expectedException.expect(IOException.class);
+    expectedException.expectMessage(Matchers.is("open stream failed"));
+
+    multipartFile.getBytes();
+  }
+
+  @Test
+  public void transferTo() throws IllegalStateException, IOException {
+    File dest = new File("/dest");
+    Holder<String> destName = new Holder<>();
+    new MockUp<Part>(part) {
+      @Mock
+      void write(String fileName) throws IOException {
+        destName.value = fileName;
+      }
+    };
+
+    multipartFile.transferTo(dest);
+    Assert.assertEquals(dest.getPath(), destName.value);
+  }
+}


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services