我可以在img标记中明确指定MIME类型

时间:2014-04-16 16:54:41

标签: html image mime-types

我试图在网页上显示favicon.ico而不是快捷图标,而是在页面正文中显示图像。在我们在IE中的测试服务器上,图像无法显示,我们发现这是因为服务器上为.ico文件类型配置的MIME类型是image/vnd.microsoft.icon而不是{{1} }。

现在,我们能够重新配置我们的服务器并修复问题,但我想知道是否可以在image/x-icon标记中指定要使用的MIME类型,并覆盖特定文件的服务器范围设置?

3 个答案:

答案 0 :(得分:7)

好消息是,如果您不能依赖服务器提供的类型, 可以强行覆盖图像的MIME类型。坏消息是它依赖于Javascript,并且有些笨拙。

背景

我想在HTML图片代码中使用存储在Gitorious存储库中的文件。但是,服务器将“原始”文件数据标记为text/plain,这阻止了Internet Explorer显示它们。 Firefox和Chrome工作正常,所以我认为他们必须忽略提供的MIME类型,并根据图像数据找出实际格式。

问题

您无法为<img>标记明确指定MIME类型。首先,<img>标记没有type属性(与<object><embed>不同,或<source>使用的<audio>标记和<video>元素。即使他们这样做了,there's no guarantee that it would make any difference

  

此规范目前没有说明是否或如何检查媒体资源的MIME类型,或者是否或如何使用实际文件数据执行文件类型嗅探。实施者在这个问题上的意图不同,因此不清楚正确的解决方案是什么。 在此没有任何要求的情况下,HTTP规范严格要求遵循Content-Type标头优先(“Content-Type指定基础数据的媒体类型。”......“如果且仅限如果Content-Type字段没有给出媒体类型,则接收者可以尝试通过检查其内容和/或用于标识资源的URI的名称扩展来猜测媒体类型。“)。< / p>

可能的解决方案

可以通过XMLHttpRequest“手动”下载图像数据。一旦实际数据可用于Javascript,就可以通过DOM操作将其插入到页面中。这是一个示例HTML文件:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Hello, World!</title>
    <script src="ieimgfix.js"></script>
  </head>
  <body>
    <img alt="cat" src="https://gitorious.org/vector/vector/raw/0797c6f8faad3426d33d3748b07abd8c77d475a7:bin/media/Floyd-Steinberg_algorithm-original.jpg">
    <img alt="apple" src="https://gitorious.org/nanijsore/nanijsore/raw/34b9aae73b5623b9971c8d98878fdbb2a0264476:image/apple.png">
  </body>
</html>

...这里是ieimgfix.js文件的内容:

"use strict";

// This function is called when any image tag fails to load.
function fixMIME()
{

  var img = this;

  // First of all, try to guess the MIME type based on the file extension.
  var mime;
  switch (img.src.toLowerCase().slice(-4))
  {
    case ".bmp":              mime = "bmp";     break;
    case ".gif":              mime = "gif";     break;
    case ".jpg": case "jpeg": mime = "jpeg";    break;
    case ".png": case "apng": mime = "png";     break;
    case ".svg": case "svgz": mime = "svg+xml"; break;
    case ".tif": case "tiff": mime = "tiff";    break;
    default: console.log("Unknown file extension: " + img.src); return;
  }
  console.log("Couldn't load " + img.src + "; retrying as image/" + mime);

  // Attempt to download the image data via an XMLHttpRequest.
  var xhr = new XMLHttpRequest();
  xhr.onload = function()
  {
    if (this.status != 200) { return console.log("FAILED: " + img.src); }
    // Blob > ArrayBuffer: http://stackoverflow.com/a/15981017/4200092
    var reader = new FileReader();
    reader.onload = function()
    {
      // TypedArray > Base64 text: http://stackoverflow.com/a/12713326/4200092
      var data = String.fromCharCode.apply(null, new Uint8Array(this.result));
      img.src = "data:image/" + mime + ";base64," + btoa(data);
    };
    reader.readAsArrayBuffer(this.response);
  };
  xhr.open("get", this.src, true);
  xhr.responseType = "blob";
  xhr.send();

}

// This callback happens after the DOCUMENT is loaded but before IMAGES are.
document.addEventListener("readystatechange", function() {
  if (document.readyState != "interactive") { return; }
  // Add an error handler callback to all image tags in the document.
  var t = document.getElementsByTagName("img");
  for (var i = 0; i < t.length; ++i) { t[i].addEventListener("error", fixMIME, false); }
}, false);

请注意,未涵盖通过DOM操作添加到页面的任何 <img>标记,因此您需要自己附加监听器。

CORS

有趣的是,上面的代码会导致Firefox和Chrome在处理无效图片网址时抱怨CORS

铬:

  

XMLHttpRequest无法加载http://www.google.com/notarealfile.png。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此不允许原点'null'访问。响应的HTTP状态代码为404.

火狐:

  

阻止跨源请求:同源策略禁止在http://www.google.com/notarealfile.png读取远程资源。这可以通过将资源移动到同一域或启用CORS来解决。

但是,Internet Explorer 11似乎并不关心。这很好用:

  • 错误的MIME类型在Chrome / Firefox中运行良好,因此不需要XMLHttpRequest
  • 错误的MIME类型在Internet Explorer上不起作用,但XMLHttpRequest将在没有与CORS相关的问题的情况下运行。

免责声明:正确的事情是让服务器发送正确的MIME类型。这是一个相当hacky的解决方法,除非你别无选择,否则我不会推荐它。

答案 1 :(得分:4)

img元素中没有指定媒体类型的属性。如果您使用例如相反,object元素(它也适用于图像,但有一些怪癖),您可以在那里使用type属性。但它在HTML 4.01中的定义是:“此属性是可选的,但建议在指定数据时使用,因为它允许用户代理避免为不支持的内容类型加载信息。如果此属性的值与检索对象时服务器返回的HTTP Content-Type不同,则HTTP Content-Type优先。“在HTML5 CR中,它有点不同,但重点仍然是{{ <}>}属性不应该覆盖 HTTP标头 - 恰恰相反。

答案 2 :(得分:1)

我曾经尝试过;但是,我的经验一直是必须在服务器上配置它。页面中的内容应始终遵循标准文件类型,以避免将来出现问题,例如.png,.gif和.jpg。只是我的两分钱。希望它有所帮助。