![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
IdHTTPProxyServer и размер ресурса
kernel © (2008-07-01 20:06:00)Доброго времени суток, уважаемые.
Бьюсь вторые сутки над "выдачей" информации о файле перед скачиванием через "испеченный" мною на основе IdHTTPProxyServer прокси сервере.
Т.е. при скачивании файла через свой прокси, например, с помощью IE, должно сначала появиться окно, в котором мне будет хотя бы известен размер файла, после чего, в случае моего согласия, файл скачивается. Так вот дело в том, что мне не известен размер файла, пока сам этот файл не скачается полностью (например, в IE окошко сохранения файла появляется после полного скачивания этого файла), хотя без прокси все нормально. В самом прокси я передаю в заголовке ответа Content-Length, после чего само тело файла.
Кто-нибудь знает, как устранить эту проблемку?
ЗЫ: извиняюсь, если что-то коряво написал - у меня уже ночь, голова не соображает :)
(2008-11-09 15:32:00) [1]Удалено модератором
kernel (2008-07-06 17:31:00) [2]Собственно, проблема решилась установкой нового Инди, в котором можно задавать режим полнофайловой или потоковой передачи данных. Огромное спасибо umbra, ну и всем, кто откликнулся :)
kernel (2008-07-04 12:26:00) [3]
> umbra © (04.07.08 11:32) [24]
Спасибо за информацию, сейчас посмотрю новый инди :)
umbra (2008-07-04 11:32:00) [4]
> а из тсп соединения читать блоками
так оно ж потоковое. тогда всегда есть опасность, что сервер, с которого тянут может обидеться и отключиться :)
Еще вариант - скачать инди поновее, потому как тот, для которого есть автоматический инсталлятор имеет версию 10.1.5, а текущая - 10.2.3. И в ней проксисервер сильно переделан и, возможно, доведен до ума. Недостаток в том, что устанавливать придется вручную.
Скачать можно отсюда - ftp://indy.fulgan.com/ZIP/
Поросенок Винни-Пух (2008-07-04 11:16:00) [5]поскольку сокеты блокирующие, то поблочно читать можно только многократными запросами диапазона байтов ресурса. Для файлов это нормально, для страничек - нет.
не страницу поблочно тянуть, а из тсп соединения читать блоками
umbra (2008-07-04 11:13:00) [6]
> Кто-нибудь может подсказать, как по-блочно читать?
поскольку сокеты блокирующие, то поблочно читать можно только многократными запросами диапазона байтов ресурса. Для файлов это нормально, для страничек - нет.
Лучший, по-моему, выход - создать общий ресурс (типа временный файл) + два потока на клиента у прокси. Один читает ответ на запрос и пишет в файл, другой - читает записанное и шлет его клиенту. Но тут надо уже синхронизировать эти потоки так, чтобы тот, который отдает клиенту, не читал все правильно.
kernel (2008-07-04 10:45:00) [7]Кто-нибудь может подсказать, как по-блочно читать? :)
kernel (2008-07-03 19:46:00) [8]
> Поросенок Винни-Пух © (02.07.08 16:27) [18]
> ...
> достаточно иметь два вложенных цикла чтения с сервера и
> отдачи браузеру.
А почему именно два цикла?
В общем, сделал такое "по-блочное" чтение:
var
LStream: TIdStream;
StreamBuf: TIdBytes;
DocSize: Integer;
begin
LStream := TIdMemoryStream.Create; try
ReqBlock := not RequestAllow(reqUrl);
DocSize:=0;
while (ASrc.IOHandler.Connected) and
(ADest.IOHandler.Connected) do
begin
if ASrc.IOHandler.Readable then
begin
ASrc.IOHandler.ReadBytes(StreamBuf, -1, false);
ADest.IOHandler.WriteDirect(StreamBuf);
DocSize:=DocSize + SizeOf(StreamBuf);
end;
end;
// ПОЧЕМУ-ТО ДАЛЬШЕ (начиная с этой строки)
// НИЧЕГО НЕ ВЫПОЛНЯЕТСЯ
end;
Это единственное, что у меня почтизаработало.
Почему-то такой код работает через раз :(
Складывается впечатление, что происходит где-то в цикле подвисание. Иногда страницы вообще не отдаются :(
Anatoly Podgoretsky (2008-07-02 16:50:00) [9]
> Как же тогда браузер узнает размер файла, даже без прокси?
Вопрос не правильный. А вот правильный
Как же тогда браузер узнает размер файла, без моегопрокси?
Поросенок Винни-Пух (2008-07-02 16:27:00) [10]там и события особо никакие не нужны.
достаточно иметь два вложенных цикла чтения с сервера и отдачи браузеру.
ну и читать/отдавать конечно блочно, а не в стрим.
umbra (2008-07-02 16:22:00) [11]
> а твой волшебный прокси отдает только загловок, потом забивает
> на браузер и занимается высасыванием файла
да, TIdHTTPProxyServer сделан криво. Пока он не закачает весь ресурс (причем по умолчанию - в память :)), он ничего не отдает. А поскольку сокеты блокирующие, то и события никакие произойти не могут, пока весь ресурс не закачается. Его надо рихтовать и рихтовать, чтобы до ума довести :)
Поросенок Винни-Пух (2008-07-02 15:56:00) [12]а твой волшебный прокси отдает только загловок, потом забивает на браузер и занимается высасыванием файла.
Поросенок Винни-Пух (2008-07-02 15:54:00) [13]ты наверное думаешь, что ие действует так:
посылает гет или пост, читает заголовок, останавливает закачку, показывает окно с кнопкой отмена и пока не нажмешь ок не начинает качать сам контент.
только браузер делает не так да и кнопки "ок" там нет.
предположу, что получив заголовок и начав качать само тело файла, он через некоторое время асинхронно показывает окошко, в котором можно прекратить закачку.
Поросенок Винни-Пух (2008-07-02 15:50:00) [14]Как же тогда браузер узнает размер файла, даже без прокси?
из заголовка ответа конечно же.
kernel (2008-07-02 15:47:00) [15]> Поросенок Винни-Пух © (02.07.08 15:43) [11]
> ну как я и говорил.пока твой прокси не всосет четырехгиговый
> dvd рип целиком, браузер ни байта от него не получит.
Как же тогда браузер узнает размер файла, даже без прокси?
kernel (2008-07-02 15:45:00) [16]
> значит прокси кривой. Как у вас происходит отдача браузеру?
> вы видно и правда сначала все на прокси закачиваете, хотя
> хттп прокси должен создавать туннель, покоторому все идет
> без задержек.
Само тело ресурса закачивается на прокси, после чего отдается клиенту:
...
var
LStream: TIdStream;
begin
//TODO: Have an event to let the user perform stream creation
LStream := TIdMemoryStream.Create; try
ASrc.IOHandler.ReadStream(LStream, ASize, ASize = -1);
LStream.Position := 0;
DoHTTPDocument(ADocument, LStream, AHeaders); // TyT Hu4ero oco6eHHoro
// Need to recreate IdStream, DoHTTPDocument passes it as a var and user can change the
// stream that is returned
ADest.IOHandler.Write(LStream);
finally Sys.FreeAndNil(LStream); end;
...
Собственно, все это - стандартный код IdHTTPProxyServer (Indy 10), исходники которого есть в самом Delphi (2006 и т.д.).
Сам заголовок отдается раньше тела запрашиваемого ресурса (см. пост kernel © (02.07.08 13:19) [6]).
Поросенок Винни-Пух (2008-07-02 15:43:00) [17]Вообще IdHTTPProxyServer читает требуемые данные в Stream с запрашиваемого сервера, затем отсылает это браузеру
ну как я и говорил.
пока твой прокси не всосет четырехгиговый dvd рип целиком, браузер ни байта от него не получит.
Поросенок Винни-Пух (2008-07-02 15:42:00) [18]И все же, когда мы скачиваем файл без прокси, нам известно какого он размера
И что же здесь странного?
То что контент ленс не только при подаче head отдается?
umbra (2008-07-02 15:18:00) [19]значит прокси кривой. Как у вас происходит отдача браузеру? вы видно и правда сначала все на прокси закачиваете, хотя хттп прокси должен создавать туннель, покоторому все идет без задержек.
kernel (2008-07-02 13:57:00) [20]Бррр... И все же, когда мы скачиваем файл без прокси, нам известно какого он размера (см. окошко в браузере). А известно браузеру размер файла из-за полученного Content-Length. Прокси тоже сначала отправляет заголовок с Content-Length, но почему-то браузер не реагирует :/ Все это работает и без HEAD.