https://blog.csdn.net/weixin_44268320/article/details/106423951
POST /upload HTTP/1.1
Host: 127.0.0.1:8080
Content-Type: multipart/form-data; boundary=-----WebKitFormBoundaryXxfiMGIApglCZPgJ
-------WebKitFormBoundaryXxfiMGIApglCZPgJ
Content-Disposition: form-data; name="file"; filename="pstree.png"
Content-Type: image/png
-------WebKitFormBoundaryXxfiMGIApglCZPgJ
Content-Disposition: form-data; name="token"
bR3KfLEVxQNHg3K8FZYKJDJIMHBgBDe5hMjUu6gJ:aE2enHspPmBIdi9nbLYg5sNv_7Q=:eyJzY29wZSI6ImxpbnV4LW1lZGlhLWtub3dsZWRnZS1pdHVrbm93bi1jbjpwc3RyZWUucG5nIiwiZGVhZGxpbmUiOjE2MzcyMTUwMzc4ODUsInJldHVybkJvZHkiOiJ7XCJrZXlcIjpcIiQoa2V5KVwiLFwiaGFzaFwiOlwiJChldGFnKVwiLFwiZnNpemVcIjokKGZzaXplKSxcImJ1Y2tldFwiOlwiJChidWNrZXQpXCIsXCJuYW1lXCI6XCIkKHg6bmFtZSlcIn0iLCJmaWxlVHlwZSI6MCwiaW5zZXJ0T25seSI6MX0=
-------WebKitFormBoundaryXxfiMGIApglCZPgJ
Content-Disposition: form-data; name="key"
pstree.png
-------WebKitFormBoundaryXxfiMGIApglCZPgJ
Content-Disposition: form-data; name="fname"
pstree.png
-------WebKitFormBoundaryXxfiMGIApglCZPgJ--
文件上传
做接口测试怎么能少的了文件上传功能呢? 来看下使用 REST Client 编写文件上传请求:
语法介绍
REST Client 文件上传请求比普通的请求要麻烦点,因为我们需要严格的定义请求协议和格式,下面是文件上传语法示例:
单文件上传语法:
POST /API
Host: $domain
Content-Type: multipart/form-data; boundary=$boundary
--$boundary
Content-Disposition: form-data; name="file"; filename="pstree.png"
Content-Type: image/png
< /filepath/pstree.png
--$boundary--
多文件上传语法:
POST /API
Host: $domain
Content-Type: multipart/form-data; boundary=$boundary
--$boundary
Content-Disposition: form-data; name="image"; filename="pstree.png"
Content-Type: image/png
< /filepath/pstree.png
--$boundary
Content-Disposition: form-data; name="txt"; filename="example.txt"
< /filepath/example.txt
--$boundary--
单文件与多文件语法是一致的,唯一的区别就是边界的定义,注意看两则的区别,下面来说下:
注意看 Content-Type: multipart/form-data; boundary=$boundary
。
Content-Type: multipart/form-data;
指定的是请求类型协议,就是以 form 表单形式形成流输出,而 boundary=$boundary
则是定义二进制流文件边界。
boundary
后面的值定随意指定的,可以是任意字符串。如 WebKitFormBoundary
、--WebKitFormBoundaryXdfsd
都是可以的。一定要注意,这里定义的边界是用于限制接下来的二进制流数据。
接下来需要注意看如何去二进制流数据,它的格式为(注意看空行,必须严格按照如下格式):
--$boundary
Content-Disposition: form-data; name="file"; filename="pstree.png"
Content-Type: image/png
< /filepath/pstree.png
--$boundary--
二进制流数据是在两个 $boundary
之间定义,注意起始和结尾格式。比如我们定义的 $boundary
值为 WebKitFormBoundary
,那么上面的内容就是:
--WebKitFormBoundary
Content-Disposition: form-data; name="file"; filename="pstree.png"
Content-Type: image/png
< /filepath/pstree.png
--WebKitFormBoundary--
在边界起始和结束中间的内容就是需要我们定义的二进制数据,第一行就是定义文件内容(注意与起始边界之间不能有空行):
Content-Disposition: form-data; name="file"; filename="pstree.png"
name
指定的是服务端接收的 key,这个其实就是 Form 表单的 name 属性指定的值:
<body>
<div>
<input type="file" name="image">
</div>
</body>
而 filename
就是服务端收到的文件的原始文件名,这个值指定的文件名不需要与真实的文件名一致,但文件名后缀最好保持一致!
一定要注意文件定义与边界之间不能有空行,比如写成下面的形式是不行的:
--WebKitFormBoundary
<== 这里不能有空行
Content-Disposition: form-data; name="file"; filename="pstree.png"
Content-Type: image/png
定义的是你上传文件的类型,可以不指定,同样的与 Content-Disposition
之间不能有空行!
接下来需要空一行进行指定文件,紧接着就是二进制文件结束边界,格式为:
< $filepath
--$boundary--
$filepath
是你机器上的文件路径,可以是相对地址也可以是绝对地址。紧接着就是二进制流数据结束边界!比如我们示例中定义的 $boundary
值为 WebKitFormBoundary,那么结束边界就是:
--WebKitFormBoundary--
那么多文件上传呢?唯一的区别就是边界!要注意,一个文件就对应一个 $boundary
。但是结束边界只会有一个:
--$boundary <== 第一个文件
Content-Disposition: form-data; name="image"; filename="pstree.png"
Content-Type: image/png
< /filepath/pstree.png
--$boundary <== 第二个文件
Content-Disposition: form-data; name="txt"; filename="example.txt"
< /filepath/example.txt
--$boundary-- <== 在最后一个文件结尾处加结束边界
单文件请求示例
上面介绍了相关协议,下面就来稍微修改下来做个上传测试:
POST /upload
Host: 127.0.0.1:8080
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
------WebKitFormBoundary
Content-Disposition: form-data; name="file"; filename="pstree.png"
Content-Type: image/png
< /Users/mingrn97/Desktop/pstree.png
------WebKitFormBoundary--
注意 |
---|
上面定义的边界为 ----WebKitFormBoundary ,那么下面定义的二进制流数据起始边界就要在左边加上 -- ,结束边界就要在两边都加上 -- ! |
下面是服务端 Debug 截图:
name 没什么好说了,来看下 filename。这就是之前请求时指定的文件名,如果你请求时定义的 filename 值为 xx.png 那么这里得到的 flename 就是 xx.png。
接着看我们在服务端接收的类型就是 image/png,这是因为我们在定义二进制流时指定了数据类型:Content-Type: image/png
,如果不指定我们服务端收到的就是一个 NULL。
多文件请求示例
那如何同时上传多个文件呢?
注意多文件上传分为两种,一种是同一个 name 多文件,第二种是每个文件都有一个 name。对应 HTML 文件上传组件如下:
<!-- 多组件上传 -->
<body>
<div>
<input type="file" name="image">
<input type="file" name="file">
</div>
</body>
<!-- 同一组件上传多文件 -->
<body>
<div>
<input type="file" multiple>
</div>
</body>
这两种形式大家肯定都不陌生,来看下怎么写:
多组件上传示例:
POST /upload
Host: 127.0.0.1:8080
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
------WebKitFormBoundary
Content-Disposition: form-data; name="file"; filename="example.txt"
Content-Type: text/plain
< /Users/kali/example.txt
------WebKitFormBoundary <=== 注意这里
Content-Disposition: form-data; name="image"; filename="pstree.png"
Content-Type: image/png
< /Users/kali/pstree.png
------WebKitFormBoundary--
多文件上传唯一要注意的是两个二进制流数据之间使用 --$boundary
做分割,而不是 --$boundary--
。相应的,以 Java 为例。后台就需要定义两个 MultipartFile,一个指定名称为 file
一个指定名称为 image
就好了(如下图)。当然如果不想麻烦可以直接使用 MultipartHttpServletRequest 对象接收然后循环便利文件流即可~
单组件上传示例
但组件上传多文件与多组件上传唯一的区别就是 name 值。我们只需要使 name 值一样即可:
POST /upload
Host: 127.0.0.1:8080
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
------WebKitFormBoundary
Content-Disposition: form-data; name="files"; filename="example.txt"
Content-Type: text/plain
< /Users/kali/example.txt
------WebKitFormBoundary
Content-Disposition: form-data; name="files"; filename="pstree.png"
Content-Type: image/png
< /Users/kali/pstree.png
------WebKitFormBoundary--
注意看 name 值,两个都是 files(注意一定要保证 filename 值不同)。这样后台服务代码直接使用一个数组或列表接收即可: