Multipart/form-data и UTF-8 в приложении ASP Classic
У меня проблема, которую я действительно не понимаю.
Я пытаюсь загрузить файлы в классическом приложении asp без использования внешнего компонента. Я также хочу опубликовать текст, который будет храниться в БД.
Файл загружается отлично, я использую этот код: Загрузить файлы без COM v3 от Lewis E. Moten III
Проблема - это поля ввода других форм. Я использую UTF-8, но они не входят в UTF-8. I. Шведские символы å ä и ö отображаются как вопросительные знаки, если я распечатываю их с помощью Response.Write.
Я сохранил файлы в UTF-8 (с спецификацией), я добавил метатег, чтобы сообщить страницу в UTF-8. Я установил Response.CharSet = "UTF-8".
Функция преобразования из двоичного в строку выглядит так (это единственное место, о котором я могу думать, что это может быть неправильно, так как в комментариях сказано, что он тянет символы ANSI, но я думаю, что он должен вызывать символы Unicode):
Private Function CStrU(ByRef pstrANSI)
' Converts an ANSI string to Unicode
' Best used for small strings
Dim llngLength ' Length of ANSI string
Dim llngIndex ' Current position
' determine length
llngLength = LenB(pstrANSI)
' Loop through each character
For llngIndex = 1 To llngLength
' Pull out ANSI character
' Get Ascii value of ANSI character
' Get Unicode Character from Ascii
' Append character to results
CStrU = CStrU & Chr(AscB(MidB(pstrANSI, llngIndex, 1)))
Next
End Function
Я создал тестовую страницу asp (multiparttest.asp), чтобы ее реплицировать, необходимо загрузить материал из Lewis E. Moten, чтобы он работал (я добавил его файлы в поддире, называемый upload).
<%Response.CharSet = "UTF-8" %>
<!--#INCLUDE FILE="upload/clsUpload.asp"-->
<html>
<head>
<title>Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<%
Set objUpload = New clsUpload
Response.Write( objUpload.Fields("testInput").Value )
%>
<form method="post" enctype="multipart/form-data" action="multiparttest.asp">
<input type="text" name="testInput" />
<input type="submit" value="submit" />
</form>
</body>
</html>
Я захватил запрос с использованием заголовков LiveHTTP в Firefox и сохранил его как файл UTF-8, шведские символы выглядят так, как должны (они не выглядели нормально в графическом интерфейсе LiveHTTP, но я предполагаю, что GUI сам не использует правильную кодировку). Вот как выглядит запрос POST:
http://localhost/testsite/multiparttest.asp
POST /testsite/multiparttest.asp HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://localhost/testsite/multiparttest.asp
Cookie: ASPSESSIONIDASBBRBTT=GLDJDBJALAMJFBFBDCCIONHF; ASPSESSIONIDAQABQBTT=DIPHILKAIICKJOIAIMILAMGE; ASPSESSIONIDCSABTCQS=KMHBLBLABKHCBGPNLMCIPPNJ
Content-Type: multipart/form-data; boundary=---------------------------7391102023625
Content-Length: 150
-----------------------------7391102023625
Content-Disposition: form-data; name="testInput"
åäö
-----------------------------7391102023625--
HTTP/1.x 200 OK
Cache-Control: private
Content-Length: 548
Content-Type: text/html; Charset=UTF-8
Server: Microsoft-IIS/7.0
X-Powered-By: ASP.NET
Date: Tue, 10 Nov 2009 14:20:17 GMT
----------------------------------------------------------
Любая помощь в этом мастере оценена!
EDIT 10/11:
Я попытался добавить все это в верхнюю часть asp файла из-за различных предложений, которые я нашел по этой проблеме в другом месте, без какого-либо другого результата.
<%@Language=VBScript codepage=65001 %>
<%Response.ContentType="text/html"%>
<%Response.Charset="UTF-8"%>
<%Session.CodePage=65001%>
EDIT 11/11:
Этот вопрос кажется связанным, Текст UTF-8 искажается, когда форма отправляется как данные multipart/form. Но они не используют ASP или IIS. Возможно ли установить кодировку символов для данных multipart/form в IIS? Я использую IIS7. Может быть, мой запрос действительно имеет неправильную кодировку? (Я действительно потерялся в мире кодирования символов прямо сейчас)
Ответы
Ответ 1
Ваш анализ CStrU верен. Предполагается, что один байтовый ANSI-символ отправляется клиентом. Он также предполагает, что кодовая страница, используемая как клиентом, так и локалью, в которой работает VBScript, одинакова.
При использовании UTF-8 допущения, сделанные CStrU, всегда будут неправильными. По-моему, языковой стандарт, который имеет 65001, не является его кодовой страницей (я думаю, что есть один или два, которые используют 65000, но это опять-таки).
Вот функция замены, предполагающая, что текст находится в UTF-8: -
Private Function CStrU(ByRef pstrANSI)
Dim llngLength '' # Length of ANSI string
Dim llngIndex '' # Current position
Dim bytVal
Dim intChar
'' # determine length
llngLength = LenB(pstrANSI)
'' # Loop through each character
llngIndex = 1
Do While llngIndex <= llngLength
bytVal = AscB(MidB(pstrANSI, llngIndex, 1))
llngIndex = llngIndex + 1
If bytVal < &h80 Then
intChar = bytVal
ElseIf bytVal < &hE0 Then
intChar = (bytVal And &h1F) * &h40
bytVal = AscB(MidB(pstrANSI, llngIndex, 1))
llngIndex = llngIndex + 1
intChar = intChar + (bytVal And &h3f)
ElseIf bytVal < &hF0 Then
intChar = (bytVal And &hF) * &h1000
bytVal = AscB(MidB(pstrANSI, llngIndex, 1))
llngIndex = llngIndex + 1
intChar = intChar + (bytVal And &h3F) * &h40
bytVal = AscB(MidB(pstrANSI, llngIndex, 1))
llngIndex = llngIndex + 1
intChar = intChar + (bytVal And &h3F)
Else
intChar = &hBF
End If
CStrU = CStrU & ChrW(intChar)
Loop
End Function
Обратите внимание, что при корректировке CStrU для UTF-8 вывод вашей страницы примера выглядит неправильно. Также необходимо указать настройку Codepage файла на 65001. Поскольку вы устанавливаете CharSet, отправленный клиенту на "UTF-8", вам также нужно указать ASP для использования кодовой страницы UTF-8 при кодировании текста, написанного с помощью Response.Write.
Ответ 2
Я не знаю, будет ли это какая-то помощь, но я работал с некоторым классическим ASP кодом для использования утилиты SWFUpload ( Flash-плагин, который позволяет загружать несколько файлов в пакетном режиме).
Пример кода ASP содержит некоторый всеобъемлющий код, который сортирует декодирование байтов/юникодов и похож на то, что вы упоминаете относительно chr (AscB (MidB (... - возможно, второй пример может пролить свет на вашу проблему.
Ответ 3
"назад в день", я использовал ASPUpload. Было дешевле покупать, чем тратить время на борьбу с данными формы. Подобно ASP.NET, он делает регулярные поля и загружаемые файлы доступными для запроса, но он (IIRC) разбивает старый объект Form - то есть, как только вы прочитали из ASPUpload, поток ввода будет потреблен и будет пытаться для использования регулярных входных данных формы не удастся.
Вы можете использовать оба подхода в одном приложении - просто не во время одного и того же запроса страницы; выберите один или другой, в основном (обычно на основе входящего MIME).