Request.QueryString 和 Request.ServerVariables("QUERY_STRING") 不显示 UNICODE

Request.QueryString And Request.ServerVariables("QUERY_STRING") Not Displaying UNICODE

我正在向经典 ASP 应用程序添加日志记录功能,但当用户提交 UNICODE 查询时,我很难让 Request.QueryString 和 Request.ServerVariables 正确显示。

例如 -

Response.write Request.QueryString
strVar1=&strVar2=%E8%A1%8C%E9%9B%B2%E6%B5%81%E6%B0%B4&strVar3=blah1&strVar4=blah2


Response.write Request.ServerVariables("QUERY_STRING")
strVar1=&strVar2=%E8%A1%8C%E9%9B%B2%E6%B5%81%E6%B0%B4&strVar3=blah1&strVar4=blah2


然而,如果我在 Request.QueryString 中指定一个 UNICODE 变量,它会正确打印:

Response.write Request.QueryString("strVar2")
行云流水


如何让 Request.QueryString 或 Request.ServerVariables("QUERY_STRING") 包含 UNICODE?我的搜索和结果页面上确实有以下内容,并且对数据库成功执行了查询:

<%
Response.CodePage = 65001
Response.CharSet = "utf-8"
%>

为了回答 bobince 的问题,我正在尝试记录搜索词和提交它们的页面 - 如果有更好的方法来做到这一点,我会洗耳恭听:

'Enable Logging: writes to MyDB.dbo.logging
'---------------------------------------------------------------------------------------------
Set cmd = Server.CreateObject("ADODB.Command")
cmd.CommandType = adCmdText
cmd.ActiveConnection = objConn

strADName = UCase(Request.ServerVariables("AUTH_USER"))

Protocol = Request.ServerVariables("SERVER_PROTOCOL")
Protocol = Left(Protocol,InStr(Request.ServerVariables("SERVER_PROTOCOL"),"/")-1)

if Request.ServerVariables("SERVER_PORT") = "80" then
port = ""
else
port = ":" & Request.ServerVariables("SERVER_PORT")
end if

CurPageURL = lcase(Protocol) & "://" & Request.ServerVariables("SERVER_NAME") &_
          port & Request.ServerVariables("SCRIPT_NAME") & "?" & _
          Request.ServerVariables("QUERY_STRING")

strSQL = "INSERT INTO MyDB.dbo.Logging([user],URL) SELECT ?, ? "
cmd.Parameters.Append (cmd.CreateParameter("User", adVarWChar, adParamInput, len(strADName),    strADName))
cmd.Parameters.Append (cmd.CreateParameter("URL", adVarWChar, adParamInput, len(CurPageURL), CurPageURL))

cmd.CommandText = strSQL
set objRS = cmd.Execute
'-----------------------------------------------------------------------------------------------

这实际上与 Unicode 无关。

Request.QueryString 做两件事。

如果不带参数使用它,它return将整个查询字符串与浏览器提交的完全一样(如上所述,与QUERY_STRING 服务器变量相同)。

如果您将它与 "strVar2" 这样的参数一起使用,它会将查询字符串拆分为参数部分,找到与参数名称 (strVar2=...) 对应的部分,然后returns 值。在这样做时,它负责 URL-解码查询字符串的组成部分,包括名称和值,因此输入中的 %xx 序列被解码为它们表示的字节序列:0xE8、0xA1 , 0x8C 等等。当您将该字节字符串打印到浏览器解码为 UTF-8 的页面时,他们将看到 行雲流水.

如果您确实需要,您可以自己对完整的查询字符串执行 URL 解码步骤。 Classic ASP 中没有用于 URL 解码的内置函数,但您可以自己编写这样的函数(参见 http://www.aspnut.com/reference/encoding.asp 中的 URLDecode),或使用

decodeURIComponent(s.replace(/\+/g, ' '))

来自 JScript。

请注意,如果您对整个 URL 字符串进行 URL 解码,您就会破坏它。例如输入查询字符串:

foo=abc%26def&bar=%e6%97%a5%e6%9c%ac%e8%aa%9e

你会得到:

foo=abc&def&bar=日本語

这对日本人来说没问题,但是 foo 值中的符号破坏了整个字符串,因此您无法再确定原始参数是什么。你通常应该只解码 URL 组件,一旦你将它们从 URL 中分离出来。这就是 ASP 为你做的:Request.QueryString("foo") 会正确地 return abc&def 这就是为什么你应该几乎总是使用该方法来检索参数的原因。

你到底想通过解码整个查询字符串来做什么?

如果这可以帮助到其他人:

我通过使用以 & 作为分隔符的拆分函数从 QUERY_STRING 中提取变量名来解决这个问题。然后我使用带有 Request.QueryString 的变量来获取值,包括带有 UNICODE 的变量。除非用户在查询中包含 & ,否则这是有效的,这种情况很少见。我确实为此设置了陷阱,所以至少在那种情况下我仍然可以在日志中看到访问的用户和页面。 Bobince 你的回答非常好,我会 select 它作为答案。

'Enable Logging: writes to MyDB.dbo.logging
'---------------------------------------------------------------------------------------------
Set cmd = Server.CreateObject("ADODB.Command")
    cmd.CommandType = adCmdText
    cmd.ActiveConnection = objConn
    cmd.CommandTimeOut = 1200

strADName = UCase(Request.ServerVariables("AUTH_USER"))

Protocol = Request.ServerVariables("SERVER_PROTOCOL")
Protocol = Left(Protocol,InStr(Request.ServerVariables("SERVER_PROTOCOL"),"/")-1)

if Request.ServerVariables("SERVER_PORT") = "80" then
   port = ""
else
   port = ":" & Request.ServerVariables("SERVER_PORT")
end if 

CurPageURL = lcase(Protocol) & "://" & Request.ServerVariables("SERVER_NAME") &_
          port & Request.ServerVariables("SCRIPT_NAME") & "?"

On Error Resume Next
a = Request.ServerVariables("QUERY_STRING")
a = split(a,"&")
for each x in a
'response.write(left(x,InStr(x,"=")-1) & "<br />")
CurPageURL = CurPageURL + left(x,InStr(x,"=")-1) + "=" + Request.QueryString(left(x,InStr(x,"=")-1)) & "&"
next

If Err.Number <> 0 Then
    CurPageURL = CurPageURL + "Error: Search Term Contained a &"
    Err.Clear
Else
    CurPageURL = left(CurPageURL,len(CurPageURL)-1)
End If

strSQL = "INSERT INTO MyDB.dbo.Logging([user],URL) SELECT ?, ? "
cmd.Parameters.Append (cmd.CreateParameter("User", adVarWChar, adParamInput, len(strADName), strADName))
cmd.Parameters.Append (cmd.CreateParameter("URL", adVarWChar, adParamInput, len(CurPageURL), CurPageURL))

cmd.CommandText = strSQL
set objRS = cmd.Execute