字符是如何通过表单传输的?

5
<head>
<meta charset="ISO-8859-7">
</head>

我一直在处理表单,发现 <meta charset="ISO-8859-7"> 标签编码文本框内的文本。但存储文件所使用的编码方法不同。
如果输入的字符不是由 <meta charset="ISO-8859-7"> 指定的编码规范之一,该字符将被引用(如referenced(&#D;))。
我原本以为表单会发送由指定编码生成的字节序列,因为无论我输入什么字符,它都会被一个编码解释成一个字节。例如,在 <meta charset="ISO-8859-7"> 下,我在表单中输入字符 "¥"
这个字符不属于该编码方式,但必须作为其代表的位置的字节发送A5,不管它是否可以被表示(这通常由任何编辑器完成)。
但是,表单不会将其发送为字节,而是将字符引用
代码:

index.php:

<?php header('Content-Type: text/html; charset=ISO-8859-7'); ?>

<head>
    <meta charset="ISO-8859-7">
</head>
<form method="post" action="encode.php" accept-charset="ISO-8859-7">
    <p><textarea name="input" maxlength="10" rows="5" cols="100"></textarea></p>
    <p><button>Submit</button></p>
</form>

encode.php:

<head>
    <meta charset="ISO-8859-7"><!-- Useless, Even if is specified the ISO-8859-1 where the "¥" exist, the form sended a reference char rather an a byte to interpret.-->
</head>
<?php
    $input=$_POST["input"];
    var_dump($input);
?>

源代码中的结果:

string(6) "&#165;"

注意:我已经测试了更改用于存储文件的编码。
index.php 中: 无论使用哪种编码来存储文件,表单始终会根据 accept-charset="" 属性或 <meta charset=""> 标签发送。
而对于 encode.php: 该字符串永远不会被文件编码。可以处理和表示,但是用于存储文件的编码与此无关。

我使用UTF-8,但我想知道这个问题。 - nEAnnam
Content-Type 头部信息是否可能发送了冲突的字符集? - cmbuckley
@cbuck 我在开头添加了 <?php header('Content-Type: text/html; charset=ISO-8859-7'); ?>,但仍然是一样的。 - nEAnnam
表单上的 enctype="multipart/form-data" 也不要漏掉。 - cmbuckley
@cbuck 已添加,仍然一样,非常感谢。 - nEAnnam
4个回答

3
问题在于表单编码不支持输入的字符。
据我所见,无论是 HTML 4 还是 HTML 5,都没有规定如果用户在表单字段中输入了一个表单编码不支持的字符,浏览器应该怎么做。
HTML 5 规定不支持的字符应该在 URL 的查询部分(因此在 GET 表单提交中)被替换为 ASCII 的 ?,但我找不到 POST 表单的相关内容。
所有浏览器(或至少 IE、FF、Chrome、Opera)似乎都同意将不支持的字符编码为 XML 实体。(更好的方法可能是警告用户并防止表单提交,但现在已经无法改变。)
解决方案当然是全程使用 UTF-8。这样所有字符都受到编码支持,就不会出现这个问题了。

¹ 2.6.3 解析URL。HTML 5,W3C工作草案2011年5月25日, 第8.1项:

如果所涉及的字符无法用编码encoding表示,则用单个0x3F八位字节(ASCII问号)替换它[...]

有趣的事实:上述仅适用于IRI查询部分(问号后面的部分)。路径部分始终使用UTF-8进行编码。当然,主机名当然使用Punycode进行编码。这真是令人费解。


那么,表单没有办法接受非编码字符的一部分吗? - nEAnnam
关于HTML5规定不支持的字符应该被替换的问题......它可能与POST方法相同,请问您能否提供相关信息的引用? - nEAnnam
  1. 很好的建议,我已经添加了一个参考。
  2. 表单没有明确定义的方式来接受不被表单编码支持的字符。(表单编码可以在<form>标签上显式给出或从文档编码中派生。)
- Søren Løvborg

1
你尝试过将字符集绑定到表单元素吗?
<form method="post" action="encode.php" accept-charset="ISO-8859-7">

例如,如果您使用utf-8编码,您首先需要对帖子进行解码:

$input=utf8_decode($_POST["input"]);

我不太确定这是否涵盖了您的主题,但我希望它能在某种程度上有所帮助 :)


谢谢,但仍然与上面相同,问题在于表单不以字节形式发送,即使我使用utf8_decode()函数,也没有任何内容可解码。至于accept-charset="ISO-8859-7",问题仍然存在。 - nEAnnam

0

字符集引用更多地涉及浏览器接收的内容(或在请求头中接受的内容),而不是您如何在表单中输入内容。

我认为您输入的内容与HTML文档中的字符集定义无关。重要的是您的键盘语言以及您如何输入字符。如果您的键盘语言带有日元符号,您的浏览器将识别该日元符号并相应地执行转换,转换成实体或字符引用。如果您想要一个日元符号,您将得到一个日元符号,而不是希腊A5表示法。


0
这可能不是您特定问题的原因,但在遇到字符编码问题时要记住一件事:使用相同的字符编码保存您的PHP脚本。否则很容易引起这种问题。

是的,这基本上是我所做的,但我对这个问题很好奇。谢谢你。 - nEAnnam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接