You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2018/04/23 09:17:40 UTC

[incubator-servicecomb-java-chassis] branch master updated: [SCB-512] download support chinese and space in file name

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/incubator-servicecomb-java-chassis.git


The following commit(s) were added to refs/heads/master by this push:
     new 43cec89  [SCB-512] download support chinese and space in file name
43cec89 is described below

commit 43cec8919f32de8311019639bc517fada8c7c704
Author: wujimin <wu...@huawei.com>
AuthorDate: Sun Apr 22 22:14:33 2018 +0800

    [SCB-512] download support chinese and space in file name
---
 .../client/CodeFirstRestTemplateSpringmvc.java     |  2 +-
 .../demo/springmvc/client/TestDownload.java        | 12 +++++--
 .../foundation/common/http/HttpUtils.java          | 39 +++++++++++-----------
 .../foundation/common/http/TestHttpUtils.java      | 34 ++++++++++++-------
 .../VertxServerResponseToHttpServletResponse.java  |  6 +++-
 ...stVertxServerResponseToHttpServletResponse.java |  6 ++--
 6 files changed, 60 insertions(+), 39 deletions(-)

diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java
index 2303cc0..79aedb6 100644
--- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java
+++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java
@@ -113,7 +113,7 @@ public class CodeFirstRestTemplateSpringmvc extends CodeFirstRestTemplate {
 
   private void testUpload(RestTemplate template, String cseUrlPrefix) throws IOException {
     String file1Content = "hello world";
-    File file1 = File.createTempFile("upload1", ".txt");
+    File file1 = File.createTempFile("测 试", ".txt");
     FileUtils.writeStringToFile(file1, file1Content);
 
     String file2Content = " bonjour";
diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestDownload.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestDownload.java
index 303c001..6472171 100644
--- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestDownload.java
+++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestDownload.java
@@ -98,9 +98,15 @@ public class TestDownload {
     futures.add(checkFile(intf.file(content)));
     futures.add(checkFuture(templateGet("file").saveAsString()));
 
-    // fix in next PR
-    //    futures.add(checkFile(intf.chineseAndSpaceFile(content)));
-    //    futures.add(checkFuture(templateGet("chineseAndSpaceFile").saveAsString()));
+    {
+      ReadStreamPart part = intf.chineseAndSpaceFile(content);
+      TestMgr.check("测 试.test.txt", part.getSubmittedFileName());
+      futures.add(checkFile(part));
+
+      part = templateGet("chineseAndSpaceFile");
+      TestMgr.check("测 试.test.txt", part.getSubmittedFileName());
+      futures.add(checkFuture(part.saveAsString()));
+    }
 
     futures.add(checkFile(intf.resource(content)));
     futures.add(checkFuture(templateGet("resource").saveAsString()));
diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpUtils.java
index deb6a97..81c27a4 100644
--- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpUtils.java
+++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpUtils.java
@@ -17,10 +17,8 @@
 package org.apache.servicecomb.foundation.common.http;
 
 import java.io.File;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
+import java.net.URI;
+import java.net.URISyntaxException;
 
 import org.springframework.util.StringUtils;
 
@@ -52,34 +50,35 @@ public final class HttpUtils {
     return null;
   }
 
-  public static String uriEncode(String value) {
-    return uriEncode(value, StandardCharsets.UTF_8.name());
-  }
-
-  public static String uriEncode(String value, String enc) {
+  public static String uriEncodePath(String path) {
     try {
-      return URLEncoder.encode(value, enc).replace("+", "%20");
-    } catch (UnsupportedEncodingException e) {
-      throw new IllegalStateException(String.format("uriEncode failed, value=\"%s\", enc=\"%s\".", value, enc), e);
+      URI uri = new URI(null, null, path, null);
+      return uri.toASCIIString();
+    } catch (URISyntaxException e) {
+      throw new IllegalArgumentException(String.format("uriEncode failed, path=\"%s\".", path), e);
     }
   }
 
-  public static String uriDecode(String value) {
-    return uriDecode(value, StandardCharsets.UTF_8.name());
-  }
+  public static String uriDecodePath(String path) {
+    if (path == null) {
+      return null;
+    }
 
-  public static String uriDecode(String value, String enc) {
     try {
-      return URLDecoder.decode(value, enc);
-    } catch (UnsupportedEncodingException e) {
-      throw new IllegalStateException(String.format("uriDecode failed, value=\"%s\", enc=\"%s\".", value, enc), e);
+      return new URI(path).getPath();
+    } catch (URISyntaxException e) {
+      throw new IllegalArgumentException(String.format("uriDecode failed, path=\"%s\".", path), e);
     }
   }
 
+  /**
+   * only used by SDK to download from  serviceComb producer<br>
+   * no need to check rtf6266's "filename*" rule.
+   */
   public static String parseFileNameFromHeaderValue(String headerValue) {
     String fileName = parseParamFromHeaderValue(headerValue, "filename");
     fileName = StringUtils.isEmpty(fileName) ? "default" : fileName;
-    fileName = uriDecode(fileName);
+    fileName = uriDecodePath(fileName);
     return new File(fileName).getName();
   }
 }
diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/http/TestHttpUtils.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/http/TestHttpUtils.java
index 18f8906..5fbd603 100644
--- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/http/TestHttpUtils.java
+++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/http/TestHttpUtils.java
@@ -16,7 +16,7 @@
  */
 package org.apache.servicecomb.foundation.common.http;
 
-import java.io.UnsupportedEncodingException;
+import java.net.URISyntaxException;
 
 import org.hamcrest.Matchers;
 import org.junit.Assert;
@@ -60,35 +60,45 @@ public class TestHttpUtils {
   }
 
   @Test
+  public void uriEncode_null() {
+    Assert.assertEquals("", HttpUtils.uriEncodePath(null));
+  }
+
+  @Test
+  public void uriDecode_null() {
+    Assert.assertNull(HttpUtils.uriDecodePath(null));
+  }
+
+  @Test
   public void uriEncode_chineseAndSpace() {
-    String encoded = HttpUtils.uriEncode("测 试");
+    String encoded = HttpUtils.uriEncodePath("测 试");
     Assert.assertEquals("%E6%B5%8B%20%E8%AF%95", encoded);
-    Assert.assertEquals("测 试", HttpUtils.uriDecode(encoded));
+    Assert.assertEquals("测 试", HttpUtils.uriDecodePath(encoded));
   }
 
   @Test
   public void uriEncode_failed() {
-    expectedException.expect(IllegalStateException.class);
-    expectedException.expectMessage(Matchers.is("uriEncode failed, value=\"\", enc=\"notExistEnc\"."));
-    expectedException.expectCause(Matchers.instanceOf(UnsupportedEncodingException.class));
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage(Matchers.is("uriEncode failed, path=\":\"."));
+    expectedException.expectCause(Matchers.instanceOf(URISyntaxException.class));
 
-    HttpUtils.uriEncode("", "notExistEnc");
+    HttpUtils.uriEncodePath(":");
   }
 
   @Test
   public void uriDecode_failed() {
-    expectedException.expect(IllegalStateException.class);
+    expectedException.expect(IllegalArgumentException.class);
     expectedException
-        .expectMessage(Matchers.is("uriDecode failed, value=\"%E6%B5%8B%20%E8%AF%95\", enc=\"notExistEnc\"."));
-    expectedException.expectCause(Matchers.instanceOf(UnsupportedEncodingException.class));
+        .expectMessage(Matchers.is("uriDecode failed, path=\":\"."));
+    expectedException.expectCause(Matchers.instanceOf(URISyntaxException.class));
 
-    HttpUtils.uriDecode("%E6%B5%8B%20%E8%AF%95", "notExistEnc");
+    HttpUtils.uriDecodePath(":");
   }
 
   @Test
   public void parseFileNameFromHeaderValue() {
     String fileName = "测 试.txt";
-    String encoded = HttpUtils.uriEncode(fileName);
+    String encoded = HttpUtils.uriEncodePath(fileName);
     Assert.assertEquals(fileName, HttpUtils.parseFileNameFromHeaderValue("xx;filename=" + encoded));
   }
 
diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxServerResponseToHttpServletResponse.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxServerResponseToHttpServletResponse.java
index 8f55886..ed77609 100644
--- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxServerResponseToHttpServletResponse.java
+++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxServerResponseToHttpServletResponse.java
@@ -29,6 +29,7 @@ import javax.ws.rs.core.Response.StatusType;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.servicecomb.foundation.common.http.HttpStatus;
+import org.apache.servicecomb.foundation.common.http.HttpUtils;
 import org.apache.servicecomb.foundation.common.part.FilePartForSend;
 import org.apache.servicecomb.foundation.vertx.stream.InputStreamToReadStream;
 import org.slf4j.Logger;
@@ -170,8 +171,11 @@ public class VertxServerResponseToHttpServletResponse extends AbstractHttpServle
     }
 
     if (!serverResponse.headers().contains(HttpHeaders.CONTENT_DISPOSITION)) {
+      // to support chinese and space filename in firefox
+      // must use "filename*", (https://tools.ietf.org/html/rtf6266)
+      String encodedFileName = HttpUtils.uriEncodePath(part.getSubmittedFileName());
       serverResponse.putHeader(HttpHeaders.CONTENT_DISPOSITION,
-          "attachment;filename=" + part.getSubmittedFileName());
+          "attachment;filename=" + encodedFileName + ";filename*=utf-8''" + encodedFileName);
     }
   }
 
diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxServerResponseToHttpServletResponse.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxServerResponseToHttpServletResponse.java
index f66dd1b..6afd964 100644
--- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxServerResponseToHttpServletResponse.java
+++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxServerResponseToHttpServletResponse.java
@@ -304,14 +304,16 @@ public class TestVertxServerResponseToHttpServletResponse {
         part.getContentType();
         result = "type";
         part.getSubmittedFileName();
-        result = "name";
+        result = "测     试";
       }
     };
     response.prepareSendPartHeader(part);
 
     Assert.assertTrue(serverResponse.isChunked());
     Assert.assertEquals("type", response.getHeader(HttpHeaders.CONTENT_TYPE));
-    Assert.assertEquals("attachment;filename=name", response.getHeader(HttpHeaders.CONTENT_DISPOSITION));
+    Assert.assertEquals(
+        "attachment;filename=%E6%B5%8B%20%20%20%20%20%E8%AF%95;filename*=utf-8''%E6%B5%8B%20%20%20%20%20%E8%AF%95",
+        response.getHeader(HttpHeaders.CONTENT_DISPOSITION));
   }
 
   @Test

-- 
To stop receiving notification emails like this one, please contact
liubao@apache.org.