HTML 中 <form/> 表单的提交,当使用 method 为 POST 时,可以指定属性 enctype,可能的值为以下三个;文档同时指出:method 中的 GET 和 POST 分别代表 HTTP 协议中的 GET 与 POST 方法,而 enctype 三个值分别都是是 MINE TYPE。
application/x-www-form-urlencoded;
multipart/form-data;
text/plain。
提交表单及其 enctype 值与 HTTP 协议的基本关系
POST 在 HTTP 协议中可以理解为从客户端像服务端提交数据最简单、常用的方法,比如在网页上输入姓名电话信息交给服务器去做再次的发送、信息处理或者直接保存。
POST 方法起初是用来向服务器输入数据的。 实际上,通常会用它来支持 HTML 的表单。表单中填好的数据通常会被送给服务器,然后由服务器将其发送到它要去的地方(比如,送到一个服务器网关程序中,然后由这个程序对其进行处理)。
不难看出这里的表单提交是将 <form/> 下所有表单控件的 name 和 value 进行了组合然后提交给服务端做后续处理。同时也很明显,之前准备的属于文件类型的 a.txt、a.html 和 binary 的实际内容并没有被提交,被提交的只是一个文件名的字符串,需要使这些二进制文件得意提交,需要使用另一个 enctype 的值 multipart/form-data,之后会讨论到。
对内容拼接和转译的规范
The control names/values are listed in the order they appear in the document. The name is separated from the value by ‘=’ and name/value pairs are separated from each other by ‘&‘.
In the case of multipart entities, in which one or more different sets of data are combined in a single body, a “multipart” media type field must appear in the entity’s header.
The body must then contain one or more body parts, each preceded by a boundary delimiter line, and the last one followed by a closing boundary delimiter line.
After its boundary delimiter line, each body part then consists of a header area, a blank line, and a body area.
Since file-upload is a feature that will benefit many applications, this proposes an extension to HTML to allow information providers to express file upload requests uniformly, and a MIME compatible representation for file upload responses.
知道了其格式的组成方式,就可以用代码手动来实现。虽然不多,在项目中也遇到过需要手动来发送 multipart/form-data 格式作为 ajax 发送的主题内容。以下就是一个最基本的伪代码实现,不过需要注意这里只是针对一个 field 中键值对的实现,实际中,更多时候需要对一个表单中的所有控件作循环处理。
multipart/form-data 和 HTML5 中的 FromData 对象
HTML5 中提供的 FormData 对象实际上就浏览器提供将页面内的 Form 打包成 multipart/form-data 格式的 API。
The FormData object lets you compile a set of key/value pairs to send using XMLHttpRequest.
It is primarily intended for use in sending form data, but can be used independently from forms in order to transmit keyed data.
The transmitted data is in the same format that the form’s submit() method would use to send the data if the form’s encoding type were set to multipart/form-data.
《RFC 7585》 中的 《4.3 Multiple Files for One Form Field》,特别针对 <input type="file" multiple/>,也就是一个 name 对应多个文件的情况作了说明:To match widely deployed implementations, multiple files MUST be sent by supplying each file in a separate part but all with the same “name” parameter. 即使用多个部分,和同一个 name 来对应一个 input 上传的多个文件。 ↩