Skip to Content

Delphi, Microsoft.XMLHTTP и кодировка

8 всего / 0 новых
Последнее
djfuntik
Молчун
Сообщения: 6
Бонусы: 5
Группы: Нет
Блог: читать!
Delphi, Microsoft.XMLHTTP и кодировка

Здраствуйте, помогите разобраться с программой.
Пытаюсь скачать страничку с сайта, но после запроса возвращаются вопросики вместо русского текста, думается кодировка виновата.

Страница содержит тег
""
если просматривать текст страницы, то текст также в 1251 кодировке, но вот запрос в моей программе возвращает строку с испорченными русскими буквами уже не поддающимся восстановлению (посимвольно проверял через коды символов - результат одни символы вопроса).

Где ошибка??

Program mods;
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, FileCtrl, Grids, Outline, DirOutln, Spin, Mask, ToolEdit,
OleServer, ComCtrls, OleCtrls, MSHTML, SHDocVw, ActiveX, ComObj;
type
TForm1 = class(TForm)
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
txt: String;
sait: String;
vHttp: OleVariant;
vHtml: WideString;
NameUser, PasswordUser: String;

begin
NameUser:='.....';
PasswordUser:='.....';
sait := 'http://.....';

vHttp := CreateOleObject('Microsoft.XMLHTTP');
vHttp.open('POST', sait, false, NameUser, PasswordUser);
{ vHttp.setRequestHeader(.........); что-то надо написать - не знаю, нигде не нашёл, все испробованные варианты результата не дали!}
vHttp.send();
vHtml := vHttp.responseText;

{ Работающий текст программы на VBA
Set oXMLHTTP = CreateObject("MSXML2.XMLHTTP")
With oXMLHTTP
.Open "GET", sURL, False
.send
sHTMLBody = .responseBody
End With
For i = 0 To UBound(sHTMLBody)
GetHTTPResponse = GetHTTPResponse & ChrW(AscW(Chr(AscB(MidB(sHTMLBody, i + 1, 1)))))
Next
Set oXMLHTTP = Nothing}
end;

end.

Дополнение #1

Добавляю съеденный текст....
Страница содержит тег МЕТА
http-equiv="Content-Type" content="text/html; charset=windows-1251"

Сандер
Администратор
Сандер аватар
ГуруМодератор
Сообщения: 1943
Бонусы: 617
Пол: Мужской
Блог: читать!

Есть информация, что XMLHTTP работает только в кодировке UTF-8, поэтому напрямую ничего не получится.

Но на просторах интернета нашел обходной путь

var xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");

var xmlDom = new ActiveXObject("Msxml2.DOMDocument.4.0");

xmlDom.loadXML("<?xml version=\"1.0\" encoding=\"windows-1251\"?>"); // Нужно только ради encoding="windows-1251"

try
{

xmlHttp.open("GET", "http://[server_here]/test.xml", false);
xmlHttp.send(xmlDom);

alert(xmlHttp.responseText)
}
catch(ex)
{
alert(ex.message)
}

djfuntik
Молчун
Сообщения: 6
Бонусы: 5
Группы: Нет
Блог: читать!

Меня интересует вариант только для Delphi (желательно для v.7), потому привёл вариант на VBA, который работает 100% и возвращает нормальную кириллицу, но просто очень долго это делает, выше приведённый пример на Delphi возвращает текст страницы буквально за секунды, но с попорченным текстом!
При том, что необходимый мне сайт видимо попался не очень удачным, т.к. с остальных сайтов возвращается нормальный текст.
Такое ощущение, что сайт на мой запрос возвращает текст в какой-то стандартной для него кодировке, после чего текстовка перекодируется во что-то и уже в таком виде попадает мне в руки....
Может кто подскажет в какую сторону рыть?

akkadites
Возмутитель спокойствия
Сообщения: 161
Бонусы: 94
Пол: Мужской
Группы: Блоггеры
Блог: читать!

попробуйте так:

xmlHttp.open("GET", "http://[server_here]/test.xml", false);
 xmlHttp.setRequestHeader("Content-type",
"text/xml, charset=windows-1251");
 xmlHttp.send(xmlDom); 

Но сомневаюсь, что это можно решить просто так. О правильном ответе должен заботиться сервер (отправлять заголовок).
Другое решение - попытаться перекодировать полученный ответ в неправильной кодировке в нужную. Но в Дельфи таких функций не знаю, есть ли...
Дальше, может если работа идёт с XML, то считывать responseXML?

Цитата:
readonly String responseText

Тело ответа (не включая заголовки), принятое от сервера к текущему моменту, или пустая строка, если данные еще не приняты. Если значение свойства ready-State меньше 3, данное свойство возвращает часть ответа, которая была принята к текущему моменту. Если значение свойства readyState равно 4, это свойство содержит полное тело ответа.

Если в ответе имеется заголовок, определяющий кодировку символов в теле ответа, используется эта кодировка, в противном случае предполагается кодировка UTF8.


Т.е. опять же сервер должен отдавать заголовок Header("Content-Type: text/html; charset=windows-1251"); или другой. Мета-тэг для браузера, здесь же XMLHTTPRequest;

__________________

TextSale.ru - Продажа/покупка уникального контента.

djfuntik
Молчун
Сообщения: 6
Бонусы: 5
Группы: Нет
Блог: читать!
Исходное сообщение от 12/13/2011 - 23:22

Сеньк, помочь не помогло, НО!!! Меня натолкнули на одну интересную мысль...
вышел из ситуации без потерь вот таким кодом:
var vHtml: Variant;
begin
.....
vHttp := CreateOleObject('Microsoft.XMLHTTP');
vHttp.open('POST', sait, false, NameUser, PasswordUser);
vHttp.send();
vHtml := vHttp.responseBody;
txt := '';
for i := 0 to Length(vHtml) do
begin
txt := txt + chr(StrToInt(IntToStr(vHtml[i])));
end;
....
end;

возможно chr(StrToInt(IntToStr(vHtml[i]))) можно заменить на чтото более адекватное, но пока мне лень разбираться, оставлю на завтра или более позднее время! Главное - желаемый результат наконец-то получен!
Надеюсь кому нибудь в будущем пригодится...

Дополнение #1

Сие "Length(vHtml)" глючило непонятно почему....
Вышел из ситуации очень просто!

idHttp1 := TIdHTTP.Create(nil);
txt := idHttp1.Get(sURL);
idHttp1.Free;

А всё остальное стёр к чертям!
Ведь говорили же мне делай сразу на индях.....

Сандер
Администратор
Сандер аватар
ГуруМодератор
Сообщения: 1943
Бонусы: 617
Пол: Мужской
Блог: читать!

прикольно )

djfuntik
Молчун
Сообщения: 6
Бонусы: 5
Группы: Нет
Блог: читать!

idHttp1 := TIdHTTP.Create(nil);
if Используется_PROXY = true then
idHttp1.ProxyParams.ProxyServer := 'xxx.xxx.xxx.xxx';
idHttp1.ProxyParams.ProxyPort := xxxx;
idHttp1.ProxyParams.ProxyUsername := '********';
idHttp1.ProxyParams.ProxyPassword := '********';
idHttp1.ProxyParams.BasicAuthentication := true;
end;
txt := idHttp1.Get(sURL);
idHttp1.Free;

Вообщем остановился пока на таком тексте, но опять подзастрял...
как определить используется прокси для соединения с инетом или не используется?

Сандер
Администратор
Сандер аватар
ГуруМодератор
Сообщения: 1943
Бонусы: 617
Пол: Мужской
Блог: читать!


procedure GetProxyData(var ProxyEnabled: boolean; var ProxyServer: string; var ProxyPort: integer);
var
ProxyInfo: PInternetProxyInfo;
Len: LongWord;
i, j: integer;
begin
Len := 4096;
ProxyEnabled := false;
GetMem(ProxyInfo, Len);
try
if InternetQueryOption(nil, INTERNET_OPTION_PROXY, ProxyInfo, Len)
then
if ProxyInfo^.dwAccessType = INTERNET_OPEN_TYPE_PROXY then
begin
ProxyEnabled:= True;
ProxyServer := ProxyInfo^.lpszProxy;
showmessage('!');
end
finally
FreeMem(ProxyInfo);
end;

if ProxyEnabled and (ProxyServer <> '') then
begin
i := Pos('http=', ProxyServer);
if (i > 0) then
begin
Delete(ProxyServer, 1, i+5);
j := Pos(';', ProxyServer);
if (j > 0) then
ProxyServer := Copy(ProxyServer, 1, j-1);
end;
i := Pos(':', ProxyServer);
if (i > 0) then
begin
ProxyPort := StrToIntDef(Copy(ProxyServer, i+1, Length(ProxyServer)-i), 0);
ProxyServer := Copy(ProxyServer, 1, i-1)
end
end;
end;

RSS-материал


Активные пользователи

ПользовательБонусы
Сандер617
Nefertity247
Tori242
robot201
Chief183
STAER140
faiters139
Mavarik121
akkadites94
staiki94