вопрос: есть html страница... скажем zalil.ru (для примера) ответ от сервера при её запросе выглядит так: Code: HTTP/1.1 200 OK Server: nginx/0.3.17 Date: Sun, 21 Mar 2010 16:22:39 GMT Content-Type: text/html; charset=windows-1251 Transfer-Encoding: chunked Connection: keep-alive e90 <html> <head> <title>Хранение файла, бесплатно закачать и скачать</title> <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon"> <link rel="stylesheet" type="text/css" media="all" href="/style/default.css" /> </head> <body> <table id="container"> <tr> <td id="content"> <div style="position:absolute; top:20px; right:20px; text-align:right;"> <form name="search" action="/page/search" method="get"> <input name="name" type="text" value="Поиск" style="width:200px;" onfocus="this.value=''" onblur="if(this.value=='')this.value='Поиск'"> </form> <br> Обладатели Flash Player могут <a href="/page/test">протестировать</a> новый аплоадер.<br><br> В некоторых подсетях плохая скорость соединения.<br> Ведутся переговоры с хостером, надеемся разрешить эту проблему. </div> <div id="center"> <form action="/upload/" name="sendform" enctype="multipart/form-data" method="post" id="sendform" onSubmit="sending()"> <input type="file" name="file" size="53" onFocus="choice()" onclick="choice()"> <input type="submit" name="submit" value=" Send " id="submit"> </form> <p>Сервис позволяет разместить файл размером не более 50 Мб.<br> Файл будет удален через 1 месяц после последнего скачивания.</p> </div> <script language="JavaScript"> var sendform; var flag; setTimeout(function() { sendform=document.getElementById("sendform"); flag=1; sendform.submit.disabled=true; sendform.submit.value=' Send '; }, 200); function choice() { if(flag==1) sendform.submit.disabled=false; } function sending() { sendform.submit.disabled=true; sendform.submit.value="Sending"; flag=0; } </script> </td> </tr> <tr> <td id="copyright"> <!-- # ECTO*COUNTER--> <script language="javascript"> document.write('<img s'+'rc="http://support.ecto.ru/counter.php'+ '?i=2&r='+escape(document.referrer)+ '" style="border:0;"/>'); </script> <noscript> <img src="http://support.ecto.ru/counter.php?i=2" border="0"/> </noscript> <!-- # ECTO*COUNTER--> <span>©2010 <a href="http://fhn.ru">fhn*createam</a></span> <a href="/page/">О проекте</a> <a href="mailto:[email protected]">Реклама</a> </td> </tr> </table> <div style="position:absolute;bottom:6;right:10;"> <[email protected] COUNTEr--><script language="JavaScript" type="text/javascript"><!-- d=document;var a='';a+=';r='+escape(d.referrer) js=10//--></script><script language="JavaScript1.1" type="text/javascript"><!-- a+=';j='+navigator.javaEnabled() js=11//--></script><script language="JavaScript1.2" type="text/javascript"><!-- s=screen;a+=';s='+s.width+'*'+s.height a+=';d='+(s.colorDepth?s.colorDepth:s.pixelDepth) js=12//--></script><script language="JavaScript1.3" type="text/javascript"><!-- js=13//--></script><script language="JavaScript" type="text/javascript"><!-- d.write('<a href="http://top.mail.ru/jump?from=956201"'+ ' target=_top><img src="http://d7.c9.be.a0.top.list.ru/counter'+ '?id=956201;t=84;js='+js+a+';rand='+Math.random()+ '" alt="Рейтинг@Mail.ru"'+' border=0 height=18 width=88/><\/a>') if(11<js)d.write('<'+'!-- ')//--></script><noscript><a target=_top href="http://top.mail.ru/jump?from=956201"><img src="http://d7.c9.be.a0.top.list.ru/counter?js=na;id=956201;t=84" border=0 height=18 width=88 alt="Рейтинг@Mail.ru"/></a></noscript><script language="JavaScript" type="text/javascript"><!-- if(11<js)d.write('--'+'>')//--></script><!--/COUNTER--> </div> <script src="http://www.google-analytics.com/urchin.js" type="text/javascript"> </script> <script type="text/javascript"> _uacct = "UA-2283330-1"; urchinTracker(); </script> </body> </html> 0 есть та же самая страница, запрошенная с изпользованием gzip - выглядит она примерно так Code: HTTP/1.1 200 OK Server: nginx/0.3.17 Date: Sun, 21 Mar 2010 16:06:59 GMT Content-Type: text/html; charset=windows-1251 Transfer-Encoding: chunked Connection: keep-alive Content-Encoding: gzip a <тут 10 символов> 6da <тут 24 строки с разными символами> 0 Собствено вопрос: 1. Откуда считать начало gzip тела (которое длинной 6da) - с начала строки, следующей за строкой с размером и до строки с нулем без учета символов переноса строки перед нулем? 2. как конвертнуть текст gzip обратно в нормальный? ф-цией (из либы ZLibEx) Code: function DecompressString(const aString: string): string; var lStr: TStringStream; lDS: TZDecompressionStream; begin lStr := TStringStream.Create(aString); try lDS := TZDecompressionStream.Create(lStr); try SetLength(Result, lDS.Size); lDS.Read(Pointer(Result)^, lDS.Size); finally lDS.Free; end; finally lStr.Free; end; end; увы не удается - пишет "data error", при том что на вход ф-ции я подаю следующее: reply:=copy(reply,pos('6da',reply)+3,1754); //1745 это 6da где reply - изначально полученный мной от сервера ответ. Прошу показать как с этим справиться конкретно на примере страницы zalil.ru, т.к. она маленькая + неизменяющаяся. Но можно и на любой другой ps. вожусь с этой *ней уже часов 6. за реальную помощь в решении вопроса преобразования gzip в обычный текст при использовании сокетов (никаких компонет, никакого инди - мне 1000-1500 потоков надо - инди убьет себя) с меня +20
Пробуй передавать на вход своей функции не переменную типа String, а какую-нибудь переменную типа TMemoryStream, так как String не сможет сохранить в себе все символы, которые передает тебе сервер.
так... окей. Начало блока gzip - пара байт: 0x1f,0x8b (так подсказал RFC 1952) длинна блока... наверное 6da (или любая другая хекс-цифра, которая идет перед шифроблоком и вероятно обозначает его длинну) тем не менее, как я не варьирую длинну блока (исходя из того, что первый символ блока - 0x1f) - все равно получаю "data error" :-( Chrome~ - хз.. ф-ция, что я указал (найденная в гугле) вроде как работает именно с переменной string. хотя фиг его знает что тут как, если быть до конца точным
http://en.wikipedia.org/wiki/Chunked_transfer_encoding то есть Code: a <тут A символов> 6da <тут 6da символов> 0 объединяешь в Code: <тут A символов><тут 6da символов> и передаешь в zlib
cpc конечно, но все равно выдает ту же ошибку. Дело в том, что основные "тесты" я провожу, конечно же, не на паге zalil.ru. Та пага, где я тестюсь идет не chunked а единым блоком...( и увы преобразовать её (как и любую другую, не-chunked) из gzip в обычный текст обозначенный выше ф-цией не получается (почему именно - фиг его знает. "data error") было бы супер, если бы гашелся кто-то, ко когда-нибудь реализовывал комбинацию delphi+windows_sockets+gzip
Мож баг в распаковщике? Ты попробуй полученный код распаковать в php и если удастся, нормально, значит баг в модуле
Распаковка gzip (взято отсюда - http://www.rsdn.ru/forum/winapi/2171857.flat.aspx): Code: BOOL WINAPI DecompressFile(HANDLE hArchFile, HANDLE hPlainFile) { HRESULT rc; IEncodingFilterFactory* pEflt=NULL; IDataFilter* pDF=NULL; BOOL bOK=TRUE; rc = CoCreateInstance( CLSID_StdEncodingFilterFac, NULL, CLSCTX_INPROC_SERVER, IID_IEncodingFilterFactory, (LPVOID *) &pEflt); if( FAILED(rc) ) return FALSE; pEflt->GetDefaultFilter(_T("gzip"), _T("text"), &pDF); if (pDF) { BYTE in_buff[32768]; BYTE out_buff[32768]; DWORD rdd=0; DWORD wrt=0; LONG proc=0; LONG outpt=0; __int64 filesize=0; __int64 processed=0; GetFileSizeEx(hArchFile, (PLARGE_INTEGER)&filesize); while (processed<filesize) { SetFilePointerEx(hArchFile, *((PLARGE_INTEGER)&processed), NULL, FILE_BEGIN); ReadFile(hArchFile, in_buff, sizeof(in_buff), &rdd, NULL); rc=pDF->DoDecode(0, sizeof(in_buff), in_buff, sizeof(out_buff), out_buff, rdd, &proc, &outpt, 0); if (FAILED(rc)) { bOK=FALSE; break; } WriteFile(hPlainFile, out_buff, outpt, &wrt, NULL); processed+=proc; } do { rc=pDF->DoDecode(0, sizeof(in_buff), in_buff, sizeof(out_buff), out_buff, 0, &proc, &outpt, 0); if (FAILED(rc)) { bOK=FALSE; break; } WriteFile(hPlainFile, out_buff, outpt, &wrt, 0); }while(outpt>0); pDF->Release(); pEflt->Release(); return bOK; } pEflt->Release(); return FALSE; } все работает, проверено может учитывал лишние \r\n символы?
я тоже нашел ф-ции для Си, и даже не для файлов, а для строк. Но все же, наверное, в названии темы не зря написано слово "Delphi" Знаешь ли, не всегда просто перевести код (который не понимаешь) с одного языка, который плохо понимаешь на другой, который, пусть даже, и знаешь более менее неплохо.
delphi zlib 1.2.3.2009 # zlib version 1.2.3 for delphi 5, 6, 7, 8, 2005, 2006, 2007, 2009 # now supports simple gzip files # includes zlib source code and c++ builder 6 project files (c++ builder 6 was used to compile c source into object files) http://www.base2ti.com/zlib.htm
Нет, ну ты в реале уникальный человек!!! Ему нужно именно расшифровать запакованные данные, а не получить чистый текст от сервака.
я это нашел и сам. только приспособить это к пакованым http запросам чета не получается...=\ может конечно мало *лся... там есть какие-то ф-ции для работы с "потоковыми данными" итд. Хотя.. все же хотелось бы по возможности увидеть готовый пример. maestro-ant - хром уже ответил. "Не паковать данные"? - я и так их(в данный момент) не пакую... потому что не умею распаковывать Но хотелось бы все-таки научиться, чтобы уменьшить затраты траффика => увеличить количество обрабатываемых http страниц в минуту.
Chrome~ попрошу без оскорблений. ErrorNeo Мой совет вполне дельный. Разве тебе критично-нужно чтоб трафик был упакованный? Если нет, то в заголовке запроса, который отсылаешь серверу нужно выкинуть строчку Accept-encoding gzip. И все! упаковка данных происходить не будет. Я так делал когда писал "подмену выдачи". gzip-тупо не нужен мне был. Она нужна для экономии трафика.
да, знаю, что либкурл поможет((( но в данном случае доделаю всё и без коспрессии, а дальше... если еще 1 приложение придется писать такое - а полюбому придется - буду уже юзать.... либкурл :'( (прогонять полтора террабафта траффика вообще без компрессии это все излишне же сурово, даже для меня) maestro-ant - да, мне критична именно экономия траффика. Без упаковки я запросы и так умею слать - да и любой дурак умеет. Не в обиду тебе.) А вот распавовывать пакованные методами дельфи - увы - далеко не каждый. Если быть точнее - то судя по этой теме вообще никто это не делал у нас при использовании вин-сок, да и... вообще хоть каким-либо методом на дельфи. обломно.
Пробовал TIdCompressorZLib прикрутить? Что-то мне кажется что не пробовал Кстати реальный пример того что библиотеки типа инди не хуже винсок. Гзип уменьшает трафф на порядка 70%, вот и посчитайте сколько страниц можно получить в инди и в винсок за промежуток времени
ErrorNeo если еспользуется Indy 9(Delphi 7), то багов в ней куча и gzip там попросту не работает. Для этого нужно скачать заплатки этой версии(там вполть до Classes) Вот архив : http://slil.ru/28913262 Распаковывешь эту папку в папку сос воей прогой и все *.pas подключаем к проекту через Project Manager, перезапускаем Delphi и используем как пытались, могу поспорить в этом беда.