【发布时间】:2020-02-16 14:59:52
【问题描述】:
测试用例
我在这里有一个实时测试用例:https://lonelearner.github.io/charset-issue/index.html
由于 HTML 包含非 ASCII 字符,如果您想在您的系统上可靠地重现此测试用例,以下是重现它的方法。您可以使用以下任何一种方法来重现它:
-
从上面的 URL 获取页面。
curl https://lonelearner.github.io/charset-issue/index.html -O -
运行这个命令:
echo " 3c21444f43545950452068746d6c3e0a3c68746d6c3e0a20203c68656164 3e0a202020203c7469746c653e636861727365742069737375653c2f7469 746c653e0a202020203c6d65746120687474702d65717569763d22436f6e 74656e742d547970652220636f6e74656e743d22746578742f68746d6c3b 20636861727365743d69736f2d383835392d31223e0a20203c2f68656164 3e0a20203c626f64793e0a202020203c703ea93c2f703e0a20203c2f626f 64793e0a3c2f68746d6c3e0a " | xxd -p -r > index.html
有趣的字节
让我们看看我们在这个问题中关注的 ISO-8859-1 编码字符。
$ curl -s https://lonelearner.github.io/charset-issue/index.html | xxd -g1
00000000: 3c 21 44 4f 43 54 59 50 45 20 68 74 6d 6c 3e 0a <!DOCTYPE html>.
00000010: 3c 68 74 6d 6c 3e 0a 20 20 3c 68 65 61 64 3e 0a <html>. <head>.
00000020: 20 20 20 20 3c 74 69 74 6c 65 3e 63 68 61 72 73 <title>chars
00000030: 65 74 20 69 73 73 75 65 3c 2f 74 69 74 6c 65 3e et issue</title>
00000040: 0a 20 20 20 20 3c 6d 65 74 61 20 68 74 74 70 2d . <meta http-
00000050: 65 71 75 69 76 3d 22 43 6f 6e 74 65 6e 74 2d 54 equiv="Content-T
00000060: 79 70 65 22 20 63 6f 6e 74 65 6e 74 3d 22 74 65 ype" content="te
00000070: 78 74 2f 68 74 6d 6c 3b 20 63 68 61 72 73 65 74 xt/html; charset
00000080: 3d 69 73 6f 2d 38 38 35 39 2d 31 22 3e 0a 20 20 =iso-8859-1">.
00000090: 3c 2f 68 65 61 64 3e 0a 20 20 3c 62 6f 64 79 3e </head>. <body>
000000a0: 0a 20 20 20 20 3c 70 3e a9 3c 2f 70 3e 0a 20 20 . <p>.</p>.
000000b0: 3c 2f 62 6f 64 79 3e 0a 3c 2f 68 74 6d 6c 3e 0a </body>.</html>.
在最后一行之前的行(偏移量000000a0处的行),第9个字节是a9。那是我们有趣的字节。这是copyright sign 的 ISO-8859-1 表示。请注意,这是 ISO-8859-1 编码符号,而不是 UTF-8。如果它是 UTF-8 编码的,则字节将为c2 a9。
元标记
为确保该 HTML 文件的内容被解释为 ISO-8859-1 编码数据,在 HTML 代码中有这个<meta> 标签:
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
本地行为
如果您使用浏览器在本地系统上打开此文件,您很可能会看到如下输出:
这是预期的,因为在本地打开文件时,没有 HTTP 服务器发送 HTTP 标头。因此,<meta> 标记中指定的iso-8859-1 编码被接受。
GitHub 行为
如果您使用浏览器访问 URL https://lonelearner.github.io/charset-issue/index.html,您很可能会看到如下输出:
这也是意料之中的。如果您注意到该页面使用 GitHub Pages 提供,并且 GitHub Pages 服务器始终返回指定 ISO-8859-1 编码的 HTTP 标头。
$ curl -sI https://lonelearner.github.io/charset-issue/index.html | grep -i content-type
content-type: text/html; charset=utf-8
由于 HTTP 标头指定了字符编码,<meta> 标签中的字符编码不再适用。
问题
我是否可以使用 HTML、JavaScript 或 CSS 覆盖 HTTP 标头中指定的字符编码,以告诉浏览器该内容应解释为 ISO-8859-1 编码,即使 HTTP 标头另有说明?
我知道我总是可以将版权符号写为 &copy; 或在文件中以 UTF-8 编码符号,但让我们考虑这样的解决方案超出了这个问题的范围,因为这是我正在处理的限制与:
-
<body>的内容以 ISO-8859-1 编码文本的形式提供给我。 - 我无法修改
<body>的内容。我必须在我的 HTML 中使用 ISO-8859-1 编码的文本。 - 我可以修改
<head>标签内的任何内容。所以我可以添加 JavaScript、CSS 或任何其他可以解决此问题的技巧。
【问题讨论】:
标签: html utf-8 character-encoding http-headers iso-8859-1