各瀏覽器對常用或者錯誤的 Content-Type 類型處理方式不一致
標準參考
content-type 用於定義用戶的瀏覽器或相關設備如何顯示將要加載的數據,或者如何處理將要加載的數據,此屬性的值可以查看 MIME 類型。
MIME (Multipurpose Internet Mail Extensions,多用途互聯網郵件擴展) 是描述消息內容類型的因特網標準。MIME 消息能包含文本、圖像、音頻、視頻以及其他應用程序專用的數據。
content-type 一般以下面的形式出現:
Content-Type: [type]/[subtype]; parameter
type 有下面的形式:
- Text:用於標準化地表示的文本信息,文本消息可以是多種字符集和或者多種格式的;
- Multipart:用於連接消息體的多個部分構成一個消息,這些部分可以是不同類型的數據;
- Application:用於傳輸應用程序數據或者二進制數據;
- Message:用於包裝一個E-mail消息;
- Image:用於傳輸靜態圖片數據;
- Audio:用於傳輸音頻或者音聲數據;
- Video:用於傳輸動態影像數據,可以是與音頻編輯在一起的視頻數據格式。
subtype 用於指定 type 的詳細形式。“type/subtype”配對的集合和與此相關的參數。下面是最經常用到的一些 MIME 類型:
- text/html(HTML 文檔);
- text/plain(純文本);
- text/css(CSS 樣式表);
- image/gif(GIF 圖像);
- image/jpeg(JPG 圖像);
- application/x-javascript(JavaScript 腳本);
- application/x-shockwave-flash(Flash);
- application/x- www-form-urlencoded(使用 HTTP 的 POST 方法提交的表單);
- multipart/form-data(同上,但主要用於表單提交時伴隨文件上傳的場合)。
關於 content-type 的詳細信息,請參考 HTML4.01 規範 6.7 Content types (MIME types) 中的內容。
關於 MIME 的相信信息,請參考 IETF 的 [RFC2045] 及 [RFC2046] 規範。
更多的 MIME 類型參見:
- http://www.utoronto.ca/webdocs/HTMLdocs/Book/Book-3ed/appb/mimetype.html
- http://www.iana.org/assignments/media-types/
問題描述
Content-Type 報頭字符串代表著服務器端發送給客戶端瀏覽器的具體數據類型,瀏覽器將根據這個信息決定如何處理得到的數據內容。比如:‘Content- Type:text/html‘ 表示著這是個 HTML 文件,需要渲染引擎解釋內容後輸出;‘Content-Type: application/octet-stream‘ 表示這是個二進制流,需要下載到本地後由用戶端環境決定如何使用。
每個瀏覽器內置支持的 Content-Type 類型表各不相同,這導致了某些類型字符串在某些瀏覽器下不被識別;另外,如果出現錯誤的 Content-Type 類型,各個瀏覽器又會以不同的方式處理。
造成的影響
未知的或者是錯誤的 Content-Type 類型,在各個瀏覽器中處理方式不一致,草率對待將有可能使得同一文件在各種瀏覽器中展現方式完全不同。
受影響的瀏覽器
所有瀏覽器 |
---|
問題分析
創建一個 Web 服務器,如 Apache。在服務器上編寫一段動態代碼,如:ct_test.php
<?php $contentTypeList = array( ‘0‘=>‘Content-Type: text/plain‘, ‘1‘=>‘Content-Type: application/octet-stream‘, ‘2‘=>‘Content-Type: application/x-rar-compressed‘, ‘3‘=>‘Content-Type: application/zip‘, ‘4‘=>‘Content-Type: application/x-shockwave-flash‘, ‘5‘=>‘Content-Type: video/quicktime‘, ‘6‘=>‘Content-Type: video/mp4‘, ‘7‘=>‘Content-Type: audio/mpeg‘, ‘8‘=>‘Content-Type: image/jpeg‘, ‘9‘=>‘Content-Type: image/gif‘, ‘10‘=>‘Content-Type: image/png‘, ‘11‘=>‘Content-Type: application‘, ‘12‘=>‘Content-Type: audio‘, ‘13‘=>‘Content-Type: video‘, ‘14‘=>‘Content-Type: image‘, ‘15‘=>‘Content-Type: helloworld‘ ); header($contentTypeList[$_GET["type"]]."; charset=UTF-8"); ?>
PHP 的文件中建立了 16 種 Content-Type 類型,根據 URL 中 GET 參數值選取其中一種文件類型 HTTP 報頭發向客戶端瀏覽器。其中 11 種常用類型,4 種故意寫錯的類型,1 種完全自定義類型:
文件類型 | Content-Type 類型 | |
---|---|---|
常見類型 | 文本 | text/plain |
二進制流 | application/octet-stream | |
RAR 壓縮包 | application/x-rar-compressed | |
Zip 壓縮包 | application/zip | |
Flash 文件 | application/x-shockwave-flash | |
QuickTime 視頻 | video/quicktime | |
MP4 視頻 | video/mp4 | |
MP3 音頻 | audio/mpeg | |
JPEG 圖片 | image/jpeg | |
GIF 圖片 | image/gif | |
PNG 圖片 | image/png | |
書寫有誤類型 | 數據 | application |
音頻 | audio | |
視頻 | video | |
圖像 | image | |
瀏覽器不可識別類型 | 自定義類型 | helloworld |
分別以不同 HTTP Content-Type 報頭類型運行此段代碼,在不同的瀏覽器環境中的表現如下:
IE6 IE7 IE8 | Firefox | Chrome | Safari | Opera | |
---|---|---|---|---|---|
text/plain | 顯示文件內容 | 顯示文件內容 | 顯示文件內容 | 顯示文件內容 | 顯示文件內容 |
application/octet-stream | 顯示文件內容 | 下載文件 | 下載文件 | 下載文件 | 顯示文件內容 |
application/x-rar-compressed | 下載文件1 | 下載文件 | 下載文件 | 下載文件 | 下載文件 |
application/zip | 下載文件1 | 下載文件 | 下載文件 | 下載文件 | 下載文件 |
application/x-shockwave-flash | 試圖顯示 Flash | 試圖顯示 Flash | 試圖顯示 Flash | 試圖顯示 Flash | 試圖顯示 Flash |
video/quicktime | 下載文件 | 下載文件 | 下載文件 | 下載文件 | 下載文件 |
video/mp4 | 下載文件 | 下載文件 | 試圖播放視頻3 | 下載文件 | 下載文件 |
audio/mpeg | 下載文件 | 下載文件 | 試圖播放視頻3 | 下載文件 | 下載文件 |
image/jpeg | 顯示文件內容 | 試圖顯示圖片2 | 試圖顯示圖片 | 試圖顯示圖片 | 試圖顯示圖片 |
image/gif | 顯示文件內容 | 試圖顯示圖片2 | 試圖顯示圖片 | 試圖顯示圖片 | 試圖顯示圖片 |
image/png | 顯示文件內容 | 試圖顯示圖片2 | 試圖顯示圖片 | 試圖顯示圖片 | 試圖顯示圖片 |
application | 下載文件1 | 顯示文件內容 | 顯示文件內容 | 下載文件 | 顯示文件內容 |
audio | 下載文件1 | 顯示文件內容 | 顯示文件內容 | 下載文件 | 顯示文件內容 |
video | 下載文件1 | 顯示文件內容 | 顯示文件內容 | 下載文件 | 顯示文件內容 |
image | 下載文件1 | 顯示文件內容 | 顯示文件內容 | 下載文件 | 顯示文件內容 |
helloworld | 下載文件1 | 顯示文件內容 | 顯示文件內容 | 下載文件 | 顯示文件內容 |
【註1】:這幾種 Content-Type 類型在測試環境中的 IE6 IE7 IE8 瀏覽器彈出的下載對話框提示中,均顯示“不可識別類型”。
【註2】:Firefox 會將 URL 和一些錯誤信息輸出在圖片格式中顯示。
【註3】:Chrome 試圖使用 VIDEO 標記直接顯示這兩種格式的視頻。
由表可見:
- IE6 IE7 IE8 對於可以識別的非視頻、音頻流內容均會嗅探其內容,並且根據內容是否正常再決定如何輸出顯示;
(關於嗅探的擴展閱讀:CH9002: IE6 IE7 IE8 未按預期方式處理 content-type 為 text/plain 的內容) - Firefox Chrome 對於未知 Content-Type 的內容均直接顯示其內容,其他類型則以直接以最合適的方式處理;
- Opera 對於可以識別的視頻、音頻流內容會直接提示下載,圖片類型和 Flash 類型會試圖顯示他們,未知 Content-Type 的內容均直接顯示其內容則直接顯示其內容,但在顯示內容前不會嗅探其中的 HTML 標記。
解決方案
這個問題比較復雜,如需避免出現顯示異常,建議不要使用非法的 Content-Type 頭字符串;並且文件實際內容和數據格式應與 Content-Type 頭字符串內類型聲明一致ps: 今天碰到一個問題,firefox 輸出shtml 文本輸出,找半天發現apache 沒設置 AddType text/html .shtml 默認的.shtml被當成純文本輸出了
各瀏覽器對常用或者錯誤的 Content-Type 類型處理方式不一致