在ASP.NET 2中将ISO-8859-1转换为UTF8

3
我们有一个页面将数据以ISO-8859-1编码的方式发布到我们的ASP.NET应用程序中。
<head>
    <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
    <title>`Sample Search Invoker`</title>
</head>
<body>

<form name="advancedform" method="post" action="SearchResults.aspx">
    <input class="field" name="SearchTextBox" type="text" />
    <input class="button" name="search" type="submit" value="Search &gt;" />
</form>

并且在代码后台(SearchResults.aspx.cs)

System.Collections.Specialized.NameValueCollection postedValues = Request.Form;
String nextKey;
for (int i = 0; i < postedValues.AllKeys.Length; i++)
{
    nextKey = postedValues.AllKeys[i];

    if (nextKey.Substring(0, 2) != "__")
    {
        // Get basic search text
        if (nextKey.EndsWith(XAEConstants.CONTROL_SearchTextBox))
        {
            // Get search text value
            String sSentSearchText = postedValues[i];

            System.Text.Encoding iso88591 = System.Text.Encoding.GetEncoding("iso-8859-1");
            System.Text.Encoding utf8 = System.Text.Encoding.UTF8;

            byte[] abInput = iso88591.GetBytes(sSentSearchText);

            sSentSearchText = utf8.GetString(System.Text.Encoding.Convert(iso88591, utf8, abInput));

            this.SearchText = sSentSearchText.Replace('<', ' ').Replace('>',' ');
            this.PreviousSearchText.Value = this.SearchText;
        }
    }
}

当我们经过 Merkblätter 时,它从 postedValues[i] 中被提取出来,作为 Merkbl�tter。 原始字符串是 Merkbl%ufffdtter。

有什么想法吗?


请看一下我修改后的答案。 - AnthonyWJones
7个回答

7
您有这行代码:-
String sSentSearchText = postedValues[i];

这里发生了对POST中八位字节的解码。

问题在于META http-equiv没有告诉服务器有关编码的信息。

你可以在@Page指令中添加RequestEncoding="ISO-8859-1",停止尝试自己调整解码(因为已经完成了)。

但这也无济于事。似乎只能在web.config中指定请求编码。

最好的方法是完全停止使用ISO-8859-1,保留默认的UTF-8编码。使用限制性编码没有任何好处,只会带来痛苦。

编辑

如果更改发布表单的编码不可行,则我们似乎别无选择,只能自己处理解码。为此,请在接收代码后面包含以下两个静态方法:

private static NameValueCollection GetEncodedForm(System.IO.Stream stream, Encoding encoding)
{
    System.IO.StreamReader reader = new System.IO.StreamReader(stream, Encoding.ASCII);
    return GetEncodedForm(reader.ReadToEnd(), encoding);
}


private static NameValueCollection GetEncodedForm(string urlEncoded, Encoding encoding)
{
    NameValueCollection form = new NameValueCollection();
    string[] pairs = urlEncoded.Split("&".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

    foreach (string pair in pairs)
    {
        string[] pairItems = pair.Split("=".ToCharArray(), 2, StringSplitOptions.RemoveEmptyEntries);
        string name = HttpUtility.UrlDecode(pairItems[0], encoding);
        string value = (pairItems.Length > 1) ? HttpUtility.UrlDecode(pairItems[1], encoding) : null;
        form.Add(name, value);
    }
    return form;
}

现在不再分配:-
postedValues = Request.Form;

使用方法:

postValues = GetEncodedForm(Request.InputStream, Encoding.GetEncoding("ISO-8859-1"));

现在,您可以从其余代码中删除编码标记。

将输入页面设置为UTF-8是我的理想选择;但是,该表单嵌入在客户网站中,他们似乎不想更改编码为UTF-8,因此我正在寻找替代方案。为什么编码如此麻烦,如果我有资源,我很乐意追查并与提出这个混乱的人说话。 - Gordon Thompson
编码在ASP.NET中并不是一个问题,非常简单。不要去碰编码,让它保持默认的UTF-8即可正常工作。 - AnthonyWJones
在理想的情况下,我会使用UTF-8,但不幸的是,在这个应用程序中并不那么容易... - Gordon Thompson

2
我认为将您的编码方式添加到web.config文件中可能会解决您的问题:
<configuration>
   <system.web>
      <globalization
           fileEncoding="iso-8859-1"
           requestEncoding="iso-8859-1"
           responseEncoding="iso-8859-1"
           culture="en-US"
           uiCulture="en-US"
        />
   </system.web>
</configuration>

是的,那是我曾经考虑过的一个选项,但不幸的是还有其他问题…… - Gordon Thompson

2
我们曾经遇到了你现在面临的同样的问题。这个主题根本不是那么直观。
第一个提示是将发布数据的页面(通常是.NET中接收数据的页面)的响应编码设置为所需的表单发布编码。
但是,这只是向用户浏览器提示如何解释从服务器发送的字符集。用户可能选择手动覆盖编码方式。如果用户覆盖页面的编码方式,则发送到表单中的数据的编码方式也会发生更改(以用户设置的编码方式为准)。
然而,有一个小技巧。如果您在表单中添加一个名称为_charset_(注意下划线)的隐藏字段,大多数浏览器都会用提交表单时使用的字符集填写此表单字段。该表单字段也是HTML5规范的一部分。
因此,您可能认为您已经做好了准备,但是当在您的页面中,ASP.NET已经对所有传入表单的参数进行了URL解码。因此,当您实际获取_charset_字段的值时,包含Merkblätter的字段的值已被.NET错误地解码。
您有两个选项:
  1. 在相关ASP.NET页面中手动解析请求字符串
  2. 在Global.asax中的Application_BeginRequest中手动解析请求参数,提取_charset_字段。获取值后,将Request.ContentEncoding设置为System.Text.Encoding.GetEncoding(<_charset_字段的值>)。如果这样做,您可以像往常一样读取包含Merkblätter的字段的值,无论客户端使用哪种字符集发送该值。
在上述任何一种情况下,您都需要手动读取Request.InputStream以获取表单数据。我建议将响应编码设置为UTF-8,以便具有最多的接受字符选项,然后特别处理用户覆盖字符集的情况,如上所述。

为什么ASP.NET不能自动处理_charset_字段,而不是让我们编写Application_BeginRequest代码?这是一个charset的链接。 - David Ching

1
Function urlDecode(input)
 inp = Replace(input,"/","%2F")
 set conn = Server.CreateObject("MSXML2.ServerXMLHTTP")
 conn.setOption(2) = SXH_SERVER_CERT_IGNORE_ALL_SERVER_ERRORS
 conn.open "GET", "http://www.neoturk.net/urldecode.asp?url=" & inp, False
 conn.send ""
 urlDecode = conn.ResponseText
End Function

为了加快速度,只需在您的数据库上创建一个用于解码和编码URL的表,并在global.asa应用程序.on_start部分中读取它们。然后将它们放在应用程序对象上。 然后,在上述函数中为该应用程序对象放置一个检查过程。如果应用程序数组中不存在解码的URL,则从远程页面请求一次(提示:urldecode.asp应该在不同的服务器上,请参见:http://support.microsoft.com/default.aspx?scid=kb;en-us;Q316451),并将其插入到您的数据库中并附加到应用程序数组对象,否则从应用程序对象返回该函数。
这是我发现的最好的方法。 如果有人想要关于应用程序对象、数据库操作等更多详细信息,请通过admin@neoturk.net与我联系。
您可以在lastiktestleri.com/Home上看到上述方法成功运行。
我还使用了HeliconTech的ISAPI_Rewrite Lite版本 使用方法很简单:url = Request.ServerVariables("HTTP_X_REWRITE_URL") 这将返回指向/404.asp的确切URL。

0

我之前也遇到过同样的问题,解决方式如下:

  System.Text.Encoding iso_8859_2 = System.Text.Encoding.GetEncoding("ISO-8859-2");
  System.Text.Encoding utf_8 = System.Text.Encoding.UTF8;

  NameValueCollection n = HttpUtility.ParseQueryString("RT=A+v%E1s%E1rl%F3+nem+enged%E9lyezte+a+tranzakci%F3t", iso_8859_2);
  Response.Write(n["RT"]);

A+vásárló+nem+engedélyezte+a+tranzakciót 会如预期般返回"A vásárló nem engedélyezte a tranzakciót"。


0

这是因为您将字符串编码为ISO-8859-1,但解码时却将其视为以UTF-8编码的字符串。这肯定会破坏数据。

表单并不会仅因为您使用该编码发送页面而将数据作为ISO-8859-1进行发布。您没有为表单数据指定任何编码,因此浏览器将选择能够处理表单中数据的编码。它可能会选择ISO-8859-1,但也可能选择其他编码。

数据被发送到服务器,在那里根据浏览器指定的编码进行解码并放入Request.Form集合中。

您所要做的就是从Request.Form集合中读取已经解码的字符串。您也不必遍历集合中的所有项,因为您已经知道文本框的名称。

只需执行以下操作:

string sentSearchText = Request.Form("SearchTextBox");

表单根本没有以ISO-8859-1的方式发布数据。我认为这不是真的,浏览器使用接收到的HTML的Content-Type头来确定它将用于发布表单内容的编码。 - AnthonyWJones
嗯,我该如何将表单发布为ISO-8859-1?感谢您对Request.Form的评论,这是继承的代码,它可以工作,所以我从未考虑修复它。 - Gordon Thompson
在表单标签中使用accept-charset="ISO-8859-1"来指定编码。 - Guffa
如果服务器正在解码数据为UTF-8,则您应在表单中使用accept-charset="UTF-8"。 - Guffa
@Guffa - 谢谢,设置accept-charset="UTF-8"解决了我的问题! - David Ching
显示剩余2条评论

0
我最终做的是强制我们的应用程序使用ISO-8859-1编码。不幸的是,底层数据可能包含不适合该代码页的字符,因此在显示数据之前,我们会将127字符代码周围的所有内容转换为实体。虽然不理想,但对我们来说有效...

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