当我们在写电子邮件的时候,可以在邮件中编写文字和添加多个附件。这是应为电子邮件中采用了 MIME(Mulitpurpose Internet Mail Extensions – 多用途英特网邮件扩展)的机制。允许邮件处理文本、图片和视频等多种类型的数据。在 MIME 扩展中会使用称为多部分对象集合(Mulitpart)的方法,来处理各种不同类型的数据。

而在 HTTP 协议中也采用了多部分对象集合,允许发送一份报文主体内可以包含多种类型的实体。通常在(通过表单)上传图片或者其它文件的时候使用到多部分对象集合。

多部分对象集合包含的对象

多部份对象集合包含的对象如下:

  • mulitpart/form-data:在 Web 表单文件上传时使用;
  • mulitpart/byteranges:状态码 206(Partial Content,部分内容)响应报文包含了多个范围的内容时使用;

在 HTTP 报文中使用多部分对象集合时,需要在首部中添加 Content-Type 首部字段。

Content-Type: multipart/form-data; boundary=Aa123x

-- Aa123x
Content-Disposition: form-data; name="name"

-- Aa123x
Content-Disposition: form-data; name="image"; filename="profile.txt"
Content-Type: text/plain

---(profile.txt 的数据)---
-- Aa123x

在使用 boundary 字符串来划分多部分对象集合指明的各类实体。boundary 字符串指定的各个实体的起始行前插入“–”标记(如:– Aa123x),在多部分对象集合对应字符串的最后插入“–”标记(如:– Aa123x)作为结束。

多部分对象集合的每个部分类型中,都可以含有首部字段(例如:Content-Type: text/plain)。另外,可以在某个部分中嵌套使用多部分对象集合。

多部分对象集合的实际应用

最常见的多部分对象集合的实际应用就是使用 HTML 表单发送文件。文件是二进制数据(或被视为二进制数据),而所有其他数据都是文本数据。由于 HTTP 是一种文本协议,因此对处理二进制数据有特殊要求。

enctype 属性

enctype 属性允许您指定 Content-Type 提交表单时生成的请求中包含的 HTTP 首部信息的值。这个标头非常重要,因为它告诉服务器正在发送什么样的数据。默认情况下,其值为 application/x-www-form-urlencoded。说明这是已编码到 URL 参数中的表单数据。

<form method="post" action="https://www.yaohaixiao.com" enctype="multipart/form-data">
  <div>
    <label for="file">请选择上传文件:</label>
    <input type="file" id="file" name="myFile">
  </div>
  <div>
    <button>上传</button>
  </div>
</form>

如果要发送文件,则需要额外执行三个步骤:

  • 将该 method 属性设置为 POST 因为文件内容不能放在 URL 参数中;
  • 将值设置为 enctype="multipart/form-data"。因为数据将被拆分为多个部分,一部分用于每个文件,一部分用于表单正文中包含的文本数据(如果文本也输入到表单中);
  • 包括一个或多个 <input type="file"> 控件以允许您的用户选择要上传的文件;

现在,想必大家都应该了解为什么在使用 HTML 表单中上传文件时必须设置 enctype="multipart/form-data"吧,因为上传文件需要使用多部分对象集合才能将文本和二进制的文件的数据同时提交到服务端。