MIME types 详解

MIME type 的全称是 Multipurpose Internet Mail Extensions (MIME) ,可以标志一个文件的类型。IANA 的网站上有一个正式的 MIME type 的列表,为什么会有这个列表呢?因为并不是所有的文件类型都有 MIME type,这个MIME type 也不是服务器可以随意设置的,服务器/浏览器两头都要实现相同的标准。基本上只有使用广泛的、性能高的、安全的文件类型才会被加入,因为每加入一个,浏览器厂商、服务器厂商都要去实现,成本比较大;二来风险也比较大,如果压缩比率不高可能会浪费网络带宽,严重的可能带来安全问题。服务器正确的设置 MIME type 也非常重要,否则服务器不会解释资源,比如不会播放视频或音频等。

它的语法是 type/subtype ,中间是 / 隔开,不区分大小写(一般都是小写)。type 表示一个大类,可以是视频、音频、文本等。subtype 表示具体的格式,jpeg png 等。type 又分成两种,一种是 Discrete(独立) 的,另一种是 multpart 。

Discrete type 分为下面5种:

  1. text 文本
  2. image 图片
  3. audio 音频
  4. video 视频
  5. application 一般指二进制数据

如果不指定 subtype ,那对于文本文件默认的就是 text/pain ,二进制数据默认的是 application/octet-stream 。它表示的是“未知类型的文本文件”,并不是指所有的文本文件。举个例子,如果 <link> 标签里面的资源应该是 text/css ,如果使用 text/plain 的话,浏览器并不会把它当做一个 CSS 文件来解释。

application/octet-stream 实际上表示的是“未知的二进制数据”,因为安全考虑,浏览器不会执行它或者尝试解释它。如果 Header Content-Disposition 设置为attachment,浏览器会弹出“另外为”对话框提示保存。

Multipart 一般由多部分组成,比如 multipart/form-data 一般用于浏览器将 HTML 的表单发给服务器。其中用 Content-type 中定义的 boundary 来分割。每一个 “part” 都是一个实体,对于上传表单的字段,每一个 part 都有 HTTP header Content-Disposition 和 Content-Type。因为有 boundary 可以分割,所以 Content-Length 会被忽略。比如下面这样的一个表单:

将会发出的 HTTP 请求如下:

之前对接过一个接口,要求每个请求都要带上证书文件,我就是用的 multipart 发出的。

除了常见的这个,还有另一种叫做的 multipart/byteranges 的 MIME type。介绍这个类型之前,我们先了解一下 HTTP 协议支持的“部分相应内容”。HTTP 的请求可以设置 Range 字段,要求只返回请求部分的 bytes。(要求服务器支持,可以通过 Response 的 Accept-Ranges: bytes 判断是否支持)比如下面这个请求,就只会返回 1K 大小的内容。

发出的 HTTP 请求如下:

Response 如下:

注意这个 HTTP 响应的状态码是 “206 Partial Content”。表示返回的是部分内容。

由此,可能你已经想到,我可以一次请求多个“部分内容”吗?答案是肯定的,这个时候服务器返回的 Response 中,Header 的 Content-Type 就会是 multipart/byteranges。其中每一个“部分响应”都会带有 Header Content-Type 和 Content-Range。比如这个请求:

得到的 Response 如下:

关于 Range_requests 的更多内容可以参考 MDN 的有关部分

最后,如果 MIME type 缺失的话,客户端可能去尝试猜测它的类型。这在不同浏览器的表现是不同的,可能有安全隐患,比如某些被资源被认为是“可执行的”。服务器可以通过设置 X-Content-Type-Options 来禁止客户端进行猜测。

除了设置 MIME type之外,还有两种方法可以表示文件类型:

  1. 使用文件后缀名。在 Windows 系统中比较流行,但是这只是一种约定,并不是所有的文件的后缀名都是通用的,有意义的。特别是在 Unix 系的系统中,这只不过是“名字的一部分”而已。
  2. Magic numbers。比如 GIF89 的文件使用 47 49 46 38 39 开头,PNG 使用 89 50 4E 47 开头。但并不是所有文件都会有 Magic numbers,所以这种方法也不是100%可靠的。

在实现方面,一般 HTTP 服务器会帮你处理好 MIME type Header 的设置,比如 Nginx 会使用 mime.types 文件判断什么后缀的文件该返回什么样的 MIME type。

 

参考资料:

  1. MDN文档
  2. wiki

Leave a comment

电子邮件地址不会被公开。 必填项已用*标注