Content-Type: multipart/form-data

什么是 Content-Type 头

在http响应头或请求头中会看到一个名为Content-Type的头信息,它表示的就是文档的类型信息(Multipurpose Internet Mail Extensions or MIME type 即 MIME type

一个url其实就是一个远程文件的地址,通常一个文件可以通过后缀名来区分文件类型,但是浏览器通过url访问文件并不会使用后缀名来判断,而是使用content-type这个头来判断,这也是为什么一个html可以有不同的后缀名,甚至不要后缀都可以,只有content-type这个头设置正确即可

Content-type 头结构

Content-type表示的是文档类型,它是有一个固定的结构的

type/subtype
// 或带参数的
type/subtype;parameter=value

这里的type表示的是一个文件的大类别,例如 文本文件(text)、视频文件(video)等

subtype表示文件的子类别,例如,对于文本文件(text),其可能是常规文本(plain)、HTML文件(html)等。例如对于一个静态页来说,其MIME type就是 text/html

文档类别是可以携带参数的,例如 text/plain;charset=UTF-8

type

type分为两种:单类型(discrete)和混合类型(multipart),其中,单类型就是文档就是一个类型的文件,例如html文件、视频文件等,而混合类型则表示多种类型的文件混合类型,典型的例如在表单提交时,会有文本、文件等多种类型混合提交的,或者接收的邮件中既有文本也有文件

discrete

text、image、font、video、model、audio、example、application等

multipart

对于混合类型的http响应,除了 Content-type 为 multipart/form-data 或者 multipart/byteranges 外,其他的类型都会被浏览器当作下载文件处理(Chrome右上角显示一个另存为的提示)

混合类型实际上也是要对每个子类型进行说明的,下文中有举例

混合类型的 type 有:multipartmessage

MIME types举例

  • application/octet-stream:默认的二进制文件类型,浏览器会直接显示“另存为”的提示
  • text/plain:浏览器会直接显示,值得注意的是,浏览器不会将这种类型的文档解释为特定类型,例如你不能在里面写js或css等,浏览器不会主动解释
  • text/css、text/html、text/javascript等
  • image/apng、image/gif、image/jpeg、image/png、image/webp等
  • video/webm、audio/webm。。。

multipart/form-data

这个头常见于表单提交的请求头中,以前一直没搞懂它是怎么运作的,这里做一个解释

对于这种混合类型的文档,它的content-type实际上也是由各个类型的单类型组合而成的。例如对于以下表单:

<form
  action="http://localhost:8000/"
  method="post"
  enctype="multipart/form-data">
  <label>Name: <input name="myTextField" value="Test" /></label>
  <label><input type="checkbox" name="myCheckBox" /> Check</label>
  <label>
    Upload file: <input type="file" name="myFile" value="test.txt" />
  </label>
  <button>Send the file</button>
</form>

它里面有三个input标签,其中两个是文本类型,一个是文件类型,那么在提交时,实际的请求体为:

POST /cgi-bin/qtest HTTP/1.1
Content-Type: multipart/form-data; boundary=--aBoundaryString
Content-Length: 465

// 注:以下为请求体内容
--aBoundaryString
Content-Disposition: form-data; name="myTextField"

input of myTextField field
--aBoundaryString
Content-Disposition: form-data; name="myCheckBox"

on
--aBoundaryString
Content-Disposition: form-data; name="myFile"; filename="test.txt"
Content-Type: text/plain

Simple file.
--aBoundaryString--

可以看到,混合类型中,每个单独的类型都会被分解符号 --aBoundaryString 隔离开来,分界符前两个 -- 不可省略,后面字符串随意。每个单独类型都有单独的http请求头,例如 Content-Type 或者 Content-Disposition,Content-Disposition 在这里指定文件名称或者表单中的字段名。紧接着就是这个类型的具体内容了。

一个真实的例子

或者在 https://www.w3school.com.cn/tiy/t.asp?f=eg_html_form_submit 测试以下代码,打开控制台,填写字段和文件,点击提交即可

<form action="/demo/demo_form.asp" enctype="multipart/form-data" method="post">
   text: <input type="text" name="submit-name"><br/>
   file: <input type="file" name="files"><br/>
   <input type="submit" value="Send"/>
</form>

参考

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition

https://blog.adamchalmers.com/multipart/

Leave a Comment