它如何在内部发送文件?
该格式称为multipart/form-data
,如以下要求:enctype ='multipart / form-data'是什么意思?
我要去:
- 添加更多HTML5参考
- 用表单提交示例解释为什么他是对的
HTML5参考
有三种可能的enctype
:
如何生成示例
一旦您看到每种方法的示例,就会很清楚它们的工作方式以及何时使用每种方法。
您可以使用以下示例生成示例:
将表单保存到最小.html
文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>upload</title>
</head>
<body>
<form action="http://localhost:8000" method="post" enctype="multipart/form-data">
<p><input type="text" name="text1" value="text default">
<p><input type="text" name="text2" value="aωb">
<p><input type="file" name="file1">
<p><input type="file" name="file2">
<p><input type="file" name="file3">
<p><button type="submit">Submit</button>
</form>
</body>
</html>
我们将默认文本值设置为aωb
,这意味着aωb
因为ω
是U+03C9
,这是61 CF 89 62
UTF-8 中的字节。
创建要上传的文件:
echo 'Content of a.txt.' > a.txt
echo '<!DOCTYPE html><title>Content of a.html.</title>' > a.html
# Binary file containing 4 bytes: 'a', 1, 2 and 'b'.
printf 'a\xCF\x89b' > binary
运行我们的小回声服务器:
while true; do printf '' | nc -l 8000 localhost; done
在浏览器中打开HTML,选择文件,然后单击Submit并检查终端。
nc
打印收到的请求。
经过测试:Ubuntu 14.04.3,nc
BSD 1.105,Firefox 40。
多部分/表单数据
Firefox发送:
POST / HTTP/1.1
[[ Less interesting headers ... ]]
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150
Content-Length: 834
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="text1"
text default
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="text2"
aωb
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file1"; filename="a.txt"
Content-Type: text/plain
Content of a.txt.
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file2"; filename="a.html"
Content-Type: text/html
<!DOCTYPE html><title>Content of a.html.</title>
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file3"; filename="binary"
Content-Type: application/octet-stream
aωb
-----------------------------735323031399963166993862150--
对于二进制文件和文本字段,字节61 CF 89 62
(aωb
在UTF-8中)按字面意义发送。您可以使用进行验证nc -l localhost 8000 | hd
,其中显示字节:
61 CF 89 62
被发送(61
=='a'和62
=='b')。
因此很明显:
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150
将内容类型设置为,multipart/form-data
并说字段由给定的boundary
字符串分隔。
但请注意:
boundary=---------------------------735323031399963166993862150
--
比实际障碍少两个
-----------------------------735323031399963166993862150
这是因为标准要求边界以两个破折号开头--
。其他破折号似乎就是Firefox选择实施任意边界的方式。RFC 7578明确提到这两个前划线--
是必需的:
4.1。多部分/表单数据的“边界”参数
与其他多部分类型一样,这些部分使用边界定界符定界,该定界符使用CRLF,“-”和“ boundary”参数的值构造。
每场得到一些子报头的数据之前:Content-Disposition: form-data;
,外地name
的filename
,其次是数据。
服务器读取数据,直到下一个边界字符串为止。浏览器必须选择一个不会出现在任何字段中的边界,这就是为什么该边界在请求之间可能会有所不同的原因。
因为我们具有唯一的边界,所以不需要对数据进行编码:按原样发送二进制数据。
TODO:最佳边界尺寸(log(N)
我敢打赌)是什么,找到它的算法的名称/运行时间是多少?在以下位置询问:https : //cs.stackexchange.com/questions/39687/find-the-shortest-sequence-that-is-not-a-sub-sequence-of-a-set-of-sequences
Content-Type
由浏览器自动确定。
有人问如何确定它:浏览器如何确定上载文件的mime类型?
应用程序/ x-www-form-urlencoded
现在将更enctype
改为application/x-www-form-urlencoded
,重新加载浏览器,然后重新提交。
Firefox发送:
POST / HTTP/1.1
[[ Less interesting headers ... ]]
Content-Type: application/x-www-form-urlencoded
Content-Length: 51
text1=text+default&text2=a%CF%89b&file1=a.txt&file2=a.html&file3=binary
显然,没有发送文件数据,仅发送了基名。因此,这不能用于文件。
至于文本字段中,我们可以看到,平时打印的字符像a
和b
一个字节被送往,而不可打印的像0xCF
,并0x89
讨论了3个字节的每个:%CF%89
!
比较方式
文件上载通常包含许多不可打印的字符(例如图像),而文本形式几乎从来没有。
从示例中我们可以看到:
因此,即使我们可以使用发送文件application/x-www-form-urlencoded
,我们也不想这样做,因为它效率很低。
但是对于在文本字段中找到的可打印字符来说,这无关紧要,并且产生的开销更少,因此我们只使用它。