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-docs.git


The following commit(s) were added to refs/heads/master by this push:
     new 82ec48d  update upload and download (#323)
82ec48d is described below

commit 82ec48d647df820a80f9d5a5c09804af2443ad86
Author: liubao68 <[email protected]>
AuthorDate: Sun Feb 18 15:34:49 2024 +0800

    update upload and download (#323)
---
 .../zh_CN/docs/build-provider/http-mapping.md      |  4 +-
 .../zh_CN/docs/general-development/CORS.md         | 48 ++++++++++---
 .../docs/general-development/file-download.md      | 75 +++++++++++++------
 .../zh_CN/docs/general-development/file-upload.md  | 84 +++++++++++++---------
 .../docs/general-development/upload-download.md    |  3 +
 java-chassis-reference/zh_CN/mkdocs.yml            |  3 +-
 6 files changed, 148 insertions(+), 69 deletions(-)

diff --git a/java-chassis-reference/zh_CN/docs/build-provider/http-mapping.md 
b/java-chassis-reference/zh_CN/docs/build-provider/http-mapping.md
index 4841db4..94432a9 100644
--- a/java-chassis-reference/zh_CN/docs/build-provider/http-mapping.md
+++ b/java-chassis-reference/zh_CN/docs/build-provider/http-mapping.md
@@ -263,7 +263,9 @@ contents of multiPartParamExample2
 ----boundary-example----
 ```
 
->>> multipart/form-data 也可以表示 Form 参数, 和 application/x-www-form-urlencoded 
用法一样。为了避免混淆和简洁,建议multipart/form-data用于文件上传场景。
+>>> multipart/form-data 也可以表示 Form 参数, 和 application/x-www-form-urlencoded 
用法一样。为了避免混淆和简洁,建议multipart/form-data专用于文件上传场景。
+
+* Spring MVC
 
 ```java
 @PostMapping(path = "multiPartSpringMVCExample", consumes = 
MediaType.MULTIPART_FORM_DATA_VALUE)
diff --git a/java-chassis-reference/zh_CN/docs/general-development/CORS.md 
b/java-chassis-reference/zh_CN/docs/general-development/CORS.md
index d3d95ce..ba6efa1 100644
--- a/java-chassis-reference/zh_CN/docs/general-development/CORS.md
+++ b/java-chassis-reference/zh_CN/docs/general-development/CORS.md
@@ -1,8 +1,8 @@
-# 跨域资源共享(CORS)配置
+# 跨域资源共享(CORS)
 
 ## 概念阐述
 
-跨域资源共享(CORS, Cross-Origin Resource Sharing)允许Web服务器进行跨域访问控制,使浏览器可以更安全地进行跨域数据传输。
+跨域资源共享(CORS, Cross-Origin Resource Sharing)允许浏览器安全的进行跨域资源访问。
 
 ## 场景描述
 
@@ -12,19 +12,21 @@
 
 CORS功能在microservice.yaml文件中配置,配置项见下表所述。
 
-| 配置项 | 默认值 | 取值范围 | 是否必选 | 含义 | 注意 |
-| :--- | :--- | :--- | :--- | :--- | :--- |
-| servicecomb.cors.enabled | `false` | `true`/`false` | 否 | 是否开启CORS功能 | - |
-| servicecomb.cors.origin | `*` | - | 否 | Access-Control-Allow-Origin | - |
-| servicecomb.cors.allowCredentials | `false` | `true`/`false` | 否 | 
Access-Control-Allow-Credentials | 
根据CORS标准,当Access-Control-Allow-Credentials设置为`true`时,Access-Control-Allow-Origin不可设置为"*",否则将会抛出异常
 |
-| servicecomb.cors.allowedHeader | 无 | - | 否 | Access-Control-Allow-Headers | 
多个值使用逗号分隔 |
-| servicecomb.cors.allowedMethod | 无 | - | 否 | Access-Control-Allow-Methods | 
多个值使用逗号分隔 |
-| servicecomb.cors.exposedHeader | 无 | - | 否 | Access-Control-Expose-Headers | 
多个值使用逗号分隔 |
-| servicecomb.cors.maxAge | 无 | (0,2147483647],整型 | 否 | Access-Control-Max-Age 
| 单位是秒,如果用户不配置此项,则CORS应答中没有Access-Control-Max-Age |
+| 配置项                               | 默认值     | 取值范围              | 是否必选 | 含义  
                             | 注意                                               
                                                 |
+|:----------------------------------|:--------|:------------------|:-----|:---------------------------------|:--------------------------------------------------------------------------------------------------|
+| servicecomb.cors.enabled          | `false` | `true`/`false`    | 否    | 
是否开启CORS功能                       | -                                            
                                                     |
+| servicecomb.cors.origin           | `*`     | -                 | 否    | 
Access-Control-Allow-Origin      | 多个值使用逗号分隔                                    
                                                     |
+| servicecomb.cors.allowCredentials | `false` | `true`/`false`    | 否    | 
Access-Control-Allow-Credentials | 
根据CORS标准,当Access-Control-Allow-Credentials设置为`true`时,Access-Control-Allow-Origin不可设置为"*",否则将会抛出异常
 |
+| servicecomb.cors.allowedHeader    | 无       | -                 | 否    | 
Access-Control-Allow-Headers     | 多个值使用逗号分隔                                    
                                                     |
+| servicecomb.cors.allowedMethod    | 无       | -                 | 否    | 
Access-Control-Allow-Methods     | 多个值使用逗号分隔                                    
                                                     |
+| servicecomb.cors.exposedHeader    | 无       | -                 | 否    | 
Access-Control-Expose-Headers    | 多个值使用逗号分隔                                    
                                                     |
+| servicecomb.cors.maxAge           | 无       | (0,2147483647],整型 | 否    | 
Access-Control-Max-Age           | 
单位是秒,如果用户不配置此项,则CORS应答中没有Access-Control-Max-Age                                 
                  |
 
 
 ## 示例代码
 
+允许所有:
+
 ```yaml
 servicecomb:
   cors:
@@ -34,3 +36,27 @@ servicecomb:
     allowedMethod: PUT,DELETE
     maxAge: 3600
 ```
+
+允许单个origin:
+
+```yaml
+servicecomb:
+  cors:
+    enabled: true
+    origin: "http://test.domain:8080";
+    allowCredentials: false
+    allowedMethod: PUT,DELETE
+    maxAge: 3600
+```
+
+配置多个origin:
+
+```yaml
+servicecomb:
+  cors:
+    enabled: true
+    origin: "http://test.domain:8080,http://test.domain:9090";
+    allowCredentials: false
+    allowedMethod: PUT,DELETE
+    maxAge: 3600
+```
diff --git 
a/java-chassis-reference/zh_CN/docs/general-development/file-download.md 
b/java-chassis-reference/zh_CN/docs/general-development/file-download.md
index d579f84..6406e0a 100644
--- a/java-chassis-reference/zh_CN/docs/general-development/file-download.md
+++ b/java-chassis-reference/zh_CN/docs/general-development/file-download.md
@@ -1,31 +1,63 @@
 # 文件下载开发指导
 
-## 服务提供者开发
+Java Chassis提供了通用的 `文件下载` 支持。 如果返回值类型为 `File`、`Resource`、`InputStream`、`Part` 
等,则被认为是 `文件下载`。 文件MIME类型和文件名可以使用 `Part` 的 API 指定。
 
-文件下载支持采用 Spring MVC 和 Jax RS 开发。 因为文件下载都是 GET 方法, 因此两者的使用差异很小, 这里的例子只提供
-Spring MVC 。 
+* Spring MVC
 
-* File
+```java
+@GetMapping(path = "/downloadSpringMVCExample")
+public Part downloadSpringMVCExample(String content) throws IOException {
+    File file = createTempFile(content);
+    return new FilePart(null, file)
+        .setDeleteAfterFinished(true)
+        .setSubmittedFileName("test.bin")
+        .contentType("application/octet-stream");
+}
+```
 
-最简单的例子,接口的返回参数声明为 File 类型的参数, 即可定义一个下载接口。 
+上述接口会返回如下响应头:
 
+```text
+Content-Disposition: attachment;filename=test.bin;filename*=utf-8’’test.bin
+Content-Encoding: gzip
+Content-Type: application/octet-stream
+Transfer-Encoding: chunked
 ```
-@GetMapping(path = "/file")
-public File file(String name)
+
+* JAX-RS
+
+```java
+@GET
+@Path("/downloadSpringMVCExample")
+public Part downloadSpringMVCExample(String content) throws IOException {
+    File file = createTempFile(content);
+    return new FilePart(null, file)
+        .setDeleteAfterFinished(true)
+        .setSubmittedFileName("test.bin")
+        .contentType("application/octet-stream");
+}
+```
+
+上述接口会返回如下响应头:
+
+```text
+Content-Disposition: attachment;filename=test.bin;filename*=utf-8’’test.bin
+Content-Encoding: gzip
+Content-Type: application/octet-stream
+Transfer-Encoding: chunked
 ```
 
-* Part
+## 服务提供者开发
+
+文件下载服务端定义建议使用 `Part`, 它提供了最丰富的功能,包括指定文件名、文件删除策略以及指定Content-Type等。 Java 
Chassis也提供了下面的一些类型支持。 
 
-如果需要根据请求参数动态创建临时文件,下载完成后,将临时文件删除,可以采用 Part 类型的参数。
+* File
+
+最简单的例子,接口的返回参数声明为 File 类型的参数, 即可定义一个下载接口。 
 
 ```
 @GetMapping(path = "/file")
-public Part file(String content) throws IOException {
-File file = createTempFile(content);
-return new FilePart(null, file)
-    .setDeleteAfterFinished(true)
-    .setSubmittedFileName("test.txt");
-}
+public File file(String name)
 ```
 
 * Resource
@@ -50,8 +82,7 @@ public Resource resource() {
 }
 ```
 
-上例中,因为ByteArrayResource没有文件名的概念,所以需要实现Resource的getFilename方法,也可以通过ResponseEntity
-进行包装:
+上例中,因为ByteArrayResource没有文件名的概念,所以需要实现Resource的getFilename方法,也可以通过ResponseEntity进行包装:
 
 ```
 @GetMapping(path = "/resource")
@@ -89,9 +120,9 @@ public ResponseEntity<InputStream> download() throws 
IOException {
 
 * 文件类型判定
 
-只要没有通过ResponseEntity直接设置HttpHeaders.CONTENT\_TYPE,ServiceComb都会尝试通过File、Part、Resource中的文件名后缀进行自动判定。
+只要没有通过ResponseEntity直接设置HttpHeaders.CONTENT\_TYPE,Java 
Chassis都会尝试通过File、Part、Resource中的文件名后缀进行自动判定。
 
-ServiceComb使用java的mime 
type机制进行文件类型判定,如果业务场景中的文件后缀无法被识别,ServiceComb会默认处理为application/octet-stream
+Java Chassis使用java的mime type机制进行文件类型判定,如果业务场景中的文件后缀无法被识别,Java 
Chassis会默认处理为application/octet-stream
 
 如果这不满足要求,假设文件后缀为xyz,期望文件类型为application/file-xyz,以下方式任选一种均可解决:
 
@@ -136,18 +167,16 @@ public ResponseEntity<Part> tempFileEntity(String 
content) throws IOException {
 
 * 指定文件名
 
-只要没有通过ResponseEntity直接设置HttpHeaders.CONTENT\_DISPOSITION,ServiceComb都会尝试通过File、Part、Resource中的文件名生成HttpHeaders.CONTENT\_DISPOSITION,假设文件名为file.txt,则生成的数据如下:
+只要没有通过ResponseEntity直接设置HttpHeaders.CONTENT\_DISPOSITION,Java 
Chassis都会尝试通过File、Part、Resource中的文件名生成HttpHeaders.CONTENT\_DISPOSITION,假设文件名为file.txt,则生成的数据如下:
 
 ```
 Content-Disposition: attachment;filename=file.txt;filename*=utf-8’’file.txt
 ```
 
-不仅仅生成filename,还生成了filename\*,这是因为如果文件名中出现了中文、空格,并且filename正确地做了encode,ie、chrome都没有问题,但是firefox直接将encode后的串当作文件名直接使用了。firefox按照[https://tools.ietf.org/html/rtf6266](https://tools.ietf.org/html/rtf6266),只对filename\*进行解码。
+不仅仅生成 `filename` ,还生成了 `filename\*` 
,这是因为如果文件名中出现了中文、空格,并且filename正确地做了encode,ie、chrome都没有问题,但是firefox直接将encode后的串当作文件名直接使用了。firefox按照[https://tools.ietf.org/html/rtf6266](https://tools.ietf.org/html/rtf6266)
 ,只对 `filename\*` 进行解码。
 
 如果业务代码中直接设置Content-Disposition,需要自行处理多浏览器支持的问题。
 
-文件下载的更多用法可以通过下载 java-chassis 源码, 查看 DownloadSchema 里面的例子。
-
 ## 服务消费者开发
 
 消费者统一使用 org.apache.servicecomb.foundation.vertx.http.ReadStreamPart 处理文件下载。
diff --git 
a/java-chassis-reference/zh_CN/docs/general-development/file-upload.md 
b/java-chassis-reference/zh_CN/docs/general-development/file-upload.md
index f404542..cb48a5d 100644
--- a/java-chassis-reference/zh_CN/docs/general-development/file-upload.md
+++ b/java-chassis-reference/zh_CN/docs/general-development/file-upload.md
@@ -1,24 +1,42 @@
 # 文件上传开发指导
 
+当 HTTP 消息体是 `multipart/form-data`, 表示文件上传。
+
+```text
+GET /apps HTTP/1.1
+Host: 127.0.0.1:8080
+Accept-Language: zh
+Content-Type: multipart/form-data; boundary=----boundary-example----
+
+----boundary-example----
+Content-Disposition: form-data; name="multiPartParamExample1"
+
+contents of multiPartParamExample1
+----boundary-example----
+Content-Disposition: form-data; name="multiPartParamExample2"
+
+contents of multiPartParamExample2
+----boundary-example----
+```
+
+>>> multipart/form-data 也可以表示 Form 参数, 和 application/x-www-form-urlencoded 
用法一样。为了避免混淆和简洁,建议multipart/form-data专用于文件上传场景。
+
 ## 服务提供者开发
 服务提供者可以采用Spring MVC 或者 Jax RS定义上传接口。
 
 * 采用Spring MVC
 
 ```java
-@PostMapping(path = "/fileUpload", produces = MediaType.TEXT_PLAIN_VALUE, 
-  consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
-public String fileUpload(@RequestPart(name = "file") MultipartFile file)
-
-@PostMapping(path = "/fileUpload", produces = MediaType.TEXT_PLAIN_VALUE, 
-  consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
-public String fileUpload(@RequestPart(name = "file") Part file)
+@PostMapping(path = "multiPartSpringMVCExample", consumes = 
MediaType.MULTIPART_FORM_DATA_VALUE)
+public String multiPartSpringMVCExample(@RequestPart("multiPartParamExample1") 
MultipartFile example1,
+@RequestPart("multiPartParamExample2") MultipartFile example2)
 ```
 
 文件上传需要通过 @RequestPart 声明参数,参数类型支持 servlet 定义的 javax.servlet.http.Part 类型,也支持
 org.springframework.web.multipart.MultipartFile 类型,两种数据类型功能是一致的,MultipartFile 
的底
-层也是Part。  两种数据类型可以混合使用,比如第一个参数是Part,第二个参数是MultipartFile。 除了通过
-定义多个参数的方式上传多个文件,也可以通过List或者数组的方式声明上传多个文件。
+层也是Part。 两种数据类型可以混合使用,比如第一个参数是Part,第二个参数是MultipartFile。 
+
+除了通过定义多个参数的方式上传多个文件,也可以通过List或者数组的方式声明上传多个文件。
 
 ```java
 @PostMapping(path = "/fileUpload", produces = MediaType.TEXT_PLAIN_VALUE, 
@@ -30,29 +48,32 @@ public String fileUpload(@RequestPart(name = "files")  
List<MultipartFile> files
 public String fileUpload(@RequestPart(name = "files") MultipartFile[] files)
 ```
 
-可以通过@RequestAttribute获取其他额外信息。
+>>> 说明: 使用 List 或者数组,在HTTP参数映射中,多个文件对应于同名的 form 内容,这不是一个好的 API 设计实践。建议非必要不使用 
List 或者数组作为文件上传参数。 
+
+可以通过 `@RequestAttribute` 获取其他额外信息。
 
 ```java
-@PostMapping(path = "/fileUpload", produces = MediaType.TEXT_PLAIN_VALUE, 
-  consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
-public String fileUpload(@RequestPart(name = "files")  List<MultipartFile> 
files,
+@PostMapping(path = "multiPartSpringMVCExample", consumes = 
MediaType.MULTIPART_FORM_DATA_VALUE)
+public String multiPartSpringMVCExample(@RequestPart("multiPartParamExample1") 
MultipartFile example1,
+@RequestPart("multiPartParamExample2") MultipartFile example2,
      @RequestAttribute("message") String message)
 ```
 
-Spring MVC方式定义上传接口还有其他很多方式,可以下载java-chassis源码,并查看UploadSpringmvcSchema里面的示例。
-
+>>> 说明:`@RequestAttribute` 读取 form 内容, 并将 form 内容转换为 String 类型。 由于 
`multipart/form-data` 的 Content-Type 可能存在多样性, 建议文件上传场景不使用 `@RequestAttribute`, 
而是使用 `@RequestHeader` 传递额外信息。 
 
 * 采用Jax RS
 
 ```java
-@Path("/fileUpload")
 @POST
-@Produces(MediaType.TEXT_PLAIN)
-public String fileUpload(@FormParam(name = "file") Part file)
+@Path("multiPartJAXRSExample")
+@Consumes(MediaType.MULTIPART_FORM_DATA)
+public String multiPartJAXRSExample(@FormParam("multiPartParamExample1") Part 
example1,
+@FormParam("multiPartParamExample2") Part example2)
 ```
 
-文件上传需要通过 @FormParam 声明参数,参数类型支持servlet定义的javax.servlet.http.Part类型。除了通过
-定义多个参数的方式上传多个文件,也可以通过List或者数组的方式声明上传多个文件。
+文件上传需要通过 @FormParam 声明参数,参数类型支持servlet定义的javax.servlet.http.Part类型。
+
+除了通过定义多个参数的方式上传多个文件,也可以通过List或者数组的方式声明上传多个文件。
 
 ```java
 @Path("/fileUpload")
@@ -66,20 +87,24 @@ public String fileUpload(@FormParam(name = "files") 
List<Part> files)
 public String fileUpload(@FormParam(name = "files") Part[] files)
 ```
 
+>>> 说明: 使用 List 或者数组,在HTTP参数映射中,多个文件对应于同名的 form 内容。 尽管在非浏览器场景,使用 List 
或者数组会带来便利,但是对于浏览器上传场景则不利于理解。建议非必要不使用 List 或者数组作为文件上传参数。
+
 可以通过@FormParam获取其他额外信息。
 
 ```java
-@Path("/fileUpload")
 @POST
-@Produces(MediaType.TEXT_PLAIN)
-public String fileUpload(@FormParam(name = "files") List<Part> files,
+@Path("multiPartJAXRSExample")
+@Consumes(MediaType.MULTIPART_FORM_DATA)
+public String multiPartJAXRSExample(@FormParam("multiPartParamExample1") Part 
example1,
+@FormParam("multiPartParamExample2") Part example2,
     @FormParam("message") String message)
 ```
 
-Jax RS 方式定义上传接口还有其他很多方式,可以下载java-chassis源码,并查看 UploadJaxrsSchema 里面的示例。
+>>> 说明:`@FormParam` 读取 form 内容, 并将 form 内容转换为 String 类型。 由于 
`multipart/form-data` 的 Content-Type 可能存在多样性, 建议文件上传场景不使用 `@FormParam`, 而是使用 
`@RequestHeader` 传递额外信息。
+
 
 * 业务开发注意事项
-   
+
    通过MultipartFile或Part打开流后,记得关闭,否则上传的临时文件会无法删除,导致资源泄露和磁盘空间耗尽。
 
 ## 开发服务消费者
@@ -110,19 +135,14 @@ HttpEntity<Map<String, Object>> entity = new 
HttpEntity<>(map, headers);
 String reseult = template.postForObject(url, entity, String.class);
 ```
 
-服务消费者不区分服务提供者是 Spring MVC 或者 Jax RS。 在使用透明 RPC 或者 RestTemplate 的时候, 可以使用如下类型
-与服务提供者的文件对应: 
+服务消费者不区分服务提供者是 Spring MVC 或者 Jax RS。 在使用透明 RPC 或者 RestTemplate 的时候, 
可以使用如下类型与服务提供者的文件对应: 
 
 * java.io.File
 * javax.servlet.http.Part
 * java.io.InputStream
 * org.springframework.core.io.Resource
 
-使用InputStream时,因为是流的方式,此时没有客户端文件名的概念,服务提供者获取到的文件名为null。 
-如果既要使用内存数据,又想让producer可以获取客户端文件名,可以使用resource类型,继承
-org.springframework.core.io.ByteArrayResource,且需要实现 getFilename 方法。
-
-一样的,服务消费者还有其他灵活的使用方式,可以下载 java-chassis 代码查看调用示例。
+使用InputStream时,因为是流的方式,此时没有客户端文件名的概念,服务提供者获取到的文件名为null。 
如果既要使用内存数据,又想让producer可以获取客户端文件名,可以使用resource类型,继承org.springframework.core.io.ByteArrayResource,且需要实现
 getFilename 方法。
 
 ## 使用浏览器上传文件
 
diff --git 
a/java-chassis-reference/zh_CN/docs/general-development/upload-download.md 
b/java-chassis-reference/zh_CN/docs/general-development/upload-download.md
index 16a3422..f43ac16 100644
--- a/java-chassis-reference/zh_CN/docs/general-development/upload-download.md
+++ b/java-chassis-reference/zh_CN/docs/general-development/upload-download.md
@@ -1,3 +1,5 @@
+# 文件上传下载
+
 通过浏览器上传下载文件,是非常普遍的应用场景。java-chassis基于REST提供了上传下载功能:
 
 * 在定义服务提供者的时候,只允许采用Spring MVC 或者 Jax RS模式。 开发服务消费者不受限制,可以使用透明RPC或者RestTemplate。
@@ -10,3 +12,4 @@
 * [文件上传开发指导](file-upload.md)
 * [文件下载开发指导](file-download.md)
 
+>>> 注意: 文件上传下载不支持断点续传特性,如果上传下载大文件,需要注意上传下载时间限制,超时会导致文件上传下载失败。
diff --git a/java-chassis-reference/zh_CN/mkdocs.yml 
b/java-chassis-reference/zh_CN/mkdocs.yml
index 5c513f2..aef7eba 100644
--- a/java-chassis-reference/zh_CN/mkdocs.yml
+++ b/java-chassis-reference/zh_CN/mkdocs.yml
@@ -57,14 +57,13 @@ nav:
     - 定制序列化和反序列化方法: general-development/secret-field.md
     - 使用Context传递控制消息: general-development/context.md
     - 返回值序列化扩展: general-development/produceprocess.md
-    - 跨域资源共享(CORS配置: general-development/CORS.md
+    - 跨域资源共享(CORS): general-development/CORS.md
     - 获取熔断与实例隔离告警事件信息: general-development/AlarmEvent.md
     - 优雅停机: general-development/shutdown.md
     - 异常处理: general-development/error-handling.md
     - 微服务实例间多环境隔离: general-development/multienvironment.md
     - 线程模型: general-development/thread-model.md
     - 配置日志: general-development/config-logs.md
-
 - 多样化的通信协议功能:
     - 多协议介绍: transports/introduction.md
     - REST over HTTP(Vert.x: transports/rest-over-vertx.md

Reply via email to