multipart/form-data是HTTP POST请求提交数据时所用到的主要数据类型之一,主要用于HTML表单像服务器发送信息。和其他数据类型相比,multipart/form-data最大的特点就是可以用作文件上传的请求格式。


定义

MIME定义

MIME类型现在通常也被称为互联网媒体类型或内容类型(Content Type),是一种互联网标准,用于表示互联网上传输内容的性质和格式。在最开始,MIME被称为多用途互联网邮件扩展(Multipurpose Internet Mail Extensions),其用途只是为了扩展电子邮件标准以支持更多的数据类型。随着技术的发展,MIME框架被引入到了HTTP、SIP等其他协议中,也就扩展形成了现在的互联网媒体类型。

一个MIME类型至少由类型(type)和子类型(subtype)两部分组成,其表示方式为type/subtype。

关于MIME类型的语法结构和类型列表、类型列表等更多信息,可以参考:MIME类型

Multipart类型

MIME标准中的类型可以分为两类:独立类型和Multipart类型。

独立类型是指只代表一个单独的文件或者媒体的类型,表明了对传输数据的文件分类。例如text、application、audio、image、video等

而Multipart类型指明被传输的数据可以分为多个独立的数据块,每块数据可以拥有其独立的意义和MIME类型。

multipart/form-data

multipart/form-data是Multipart类型中最常用的子类型。最常用于HTTP POST请求的表单数据和文件的上传中。multipart/form-data的格式最早在1998年发布的RFC2388规范中定义。这一规范在2015年被新发布的RFC7578规范所取代。


multipart/form-data格式解析

当HTTP POST传输multipart/form-data类型的数据时,请求头和请求体都需要遵循相应的格式要求。一个简单的multipart/form-data类型数据传输的报文如下:

post报文

multipart/form-data请求头

在一个multipart/form-data类型数据传输的HTTP POST报文中,HTTP请求首部的Content-Type字段必须满足如下格式:

1
Content-Type: multipart/form-data; boundary=${boundstr}

其中boundary的值boundstr是一个以”–-“为开头的字符串,这个字符串是multipart/form-data请求体中不同数据块之间的分隔符。

multipart/form-data请求体

multipart/form-data请求体由多个相互独立的数据块组成,整个请求体以boundary字符串开头,每块数据之间用HTTP头部Content-Type中定义的boundary作为分隔符。在最后一个数据块之后以boundary字符串加上”–”结尾。

请求体

请求体中的每个数据块,也由一些头部字段和具体数据组成,头部字段和具体数据之间,由一个额外的换行(CRLF)隔开。常见的头部字段主要有以下几种:

  • Content-Disposition

    1
    Content-Disposition: form-data; name="xxx"

    Content-Disposition头是每个数据块必备的字段,这个字段的类型必须为form-data,此外,Content-Disposition字段中还必须包含一个额外的name参数,参数值为这块数据在原始HTML表单中对应的字段名。

    当multipart/form-data的某个数据块传输的内容是一个文件时,在其Content-Disposition字段中,还应该包含一个filename参数,用于表示所传输的文件名。例如:

    1
    Content-Disposition: form-data; name="myFile"; filename="test.txt"
  • Content-Type

    1
    Content-Type: text/plain

    Content-Type是每个数据块的可选字段,含义与HTTP请求头部的Content-Type类似,用于表明当前数据块传输数据对应的MIME类型。没有指定Content-Type字段的数据块,默认MIME类型为text/plain。

    Content-Type字段中有一个可选参数charset,用于表示传输数据作用的字符集。当传输数据为text类型时,可通过如下的方式表示数据所用的字符编码:

    1
    Content-Type: text/plain; charset=UTF-8
  • Content-Transfer-Encoding

    1
    Content-Transfer-Encoding: base64

    用于指定每块数据的编码方式,其值主要有5种:7bit、8bit、binary、base64和quoted-printable。这个字段最早设计是为了应对部分仅支持7bit编码的传输协议。而在HTTP等支持二进制数据传输的协议中,这个字段已经被逐渐弃用了。在RFC7578规范中,Content-Transfer-Encoding字段被建议不应该在HTTP等协议的multipart/form-data请求体中使用。

  • 其他字段

    RFC7578规范中定义,multipart/form-data类型不支持除Content-Disposition、Content-Type和特定情况下的Content-Transfer-Encoding以外的其他头部字段。在请求体中不应当包含其他的头部字段,而即使包含,这些其他字段也应当在服务端处理时被忽略。