multipart/form-data
通常是多部分实体,需要一直阻塞到数据读取到和 Content-Length
大小一样为止。
一个简单的multipart/form-data
请求:
第一次收到的实体数据信息:
[src\lib.rs:225] &packet.len() = 333
[src\lib.rs:226] String::from_utf8_lossy(&packet) = "POST / HTTP/1.1\r\nPostman-Token: e648a765-7e9f-46dc-bde9-2e61e3febc24\r\nContent-Type: multipart/form-data; boundary=--------------------------626641272837121778176158\r\nContent-Length: 460\r\n\r\n----------------------------626641272837121778176158\r\nContent-Disposition: form-data; name=\"img\"; filename=\"a.txt\"\r\nContent-Type: text/plain\r\n\r\n"
这里我一次读取了1024
字节,但是第一个实体读到333
字节就已经返回了。
但是可以看到Content-Length
的大小为460
现在读取到的http body
还没有这么大。
[src\lib.rs:180] &req.body.len() = 144
[src\lib.rs:181] String::from_utf8_lossy(&req.body) = "----------------------------626641272837121778176158\r\nContent-Disposition: form-data; name=\"img\"; filename=\"a.txt\"\r\nContent-Type: text/plain\r\n\r\n"
Content-Length
的大小为460
现在只收到144
,所以接下来需要继续阻塞读取,将剩下的316
字节全部读取出来
读取剩下的316
字节:
[src\lib.rs:178] &entity.len() = 316
[src\lib.rs:179] String::from_utf8_lossy(&entity) = "a\r\n----------------------------626641272837121778176158\r\nContent-Disposition: form-data; name=\"img2\"; filename=\"b.txt\"\r\nContent-Type: text/plain\r\n\r\nb\r\n----------------------------626641272837121778176158\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\najanuw\r\n----------------------------626641272837121778176158--\r\n"
现在将第一次读取的数据与之后的拼接起来大概就像这样:
----------------------------626641272837121778176158\r\n
Content-Disposition: form-data; name=\"img\"; filename=\"a.txt\"\r\n
Content-Type: text/plain\r\n\r\n
a\r\n
----------------------------626641272837121778176158\r\n
Content-Disposition: form-data; name=\"img2\"; filename=\"b.txt\"\r\n
Content-Type: text/plain\r\n\r\n
b\r\n
----------------------------626641272837121778176158\r\n
Content-Disposition: form-data; name=\"name\"\r\n\r\n
ajanuw\r\n
----------------------------626641272837121778176158--\r\n
每段数据之间使用----------------------------626641272837121778176158
分割,注意这里的626641272837121778176158
是在客户端发送时随机生成的,所以每次请求都不一样。
如果接下来没有数据,则用--\r\n
表示,可以停止读取
在----------------------------626641272837121778176158\r\n
行之后是当前节数据的信息,一直到\r\n\r\n
之后开始读取当前节的数据,直到\r\n
为止,然后开始读取下一节。
如果当前节是文件,通常会有filename
和Content-Type
等信息。
在header
头中的Content-Type: multipart/form-data; boundary=--------------------------626641272837121778176158\r\n
,消息边界是--------------------------626641272837121778176158
这和实体中的边界少了--
,可以对比下。
注意控制台打印的反斜杠:
Content-Disposition: form-data; name=\"img\"; filename=\"a.txt\"\r\n
实际上是:
Content-Disposition: form-data; name="img"; filename="a.txt"\r\n
See alse: