Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Сети > Скачать файл


Автор: Poseidon 4.9.2005, 01:09
Появилась необходимость закачать файл через https. Как это сделать не имею понятия. С этим протоколом не разу не работал. То, что работает для http, для https работать отказывается (оно и понятно). Но вот если с http я сталкивался, то с https ни разу. А реализовать нужно. Вот и прашу помощи. Если уже не функцией порадуете, каторая все делает, то хоть дайте направление, в какую сторону копать. Хотя функция была бы как раз кстати smile

Автор: Snowy 4.9.2005, 22:37
А ты попробуй набрать в поиске http://forum.vingrad.ru/index.php?act=Search&CODE=show&searchid=c79bb35ef51215d3abd6ec7e2154d9b7&search_in=posts&result_type=topics&highlite=https
Просто я уже устал рассказывать...

Автор: Poseidon 4.9.2005, 23:32
Блин, Snowy, ты как с навичком со мной. Я первым делом залез в поиск форума и поиск DRKB. На фуруме ничего по САБЖУ не нашел, в DRKB есть одна интересная статейка, но не совсем то, что нужно. Вот и пишу тут. Может кто сталкивался и уже писал такую функцию для себя. Или хоть направление дайте, куда рыть.

Автор: Alex 5.9.2005, 00:12
Poseidon, а без блинов можно? и чем тебе вот этот топик не подходит http://forum.vingrad.ru/index.php?showtopic=43642&hl=https

Автор: Poseidon 5.9.2005, 00:26
Цитата(Alex @ 5.9.2005, 00:12)
Poseidon, а без блинов можно?
Можно, извеняюсь, больше не буду smile


Цитата(Alex @ 5.9.2005, 00:12)
и чем тебе вот этот топик не подходит http://forum.vingrad.ru/index.php?showtopic=43642&hl=https
Тем, что там нет ни строчки кода (нет, есть пост Snowy, но как его прилепить к моей задаче smile ). Ну кинул я компоненты, ну связал их друг с другом. А что дальше-то делать? Просто я в этой сфере (протоколы передачи данных) ломак. И даже признаться не стыдно. А скачать файл нужно. Вот и прошу помощи у более опытных собратьев.

PS. И вот еще какая интересная штука получается. Допустим есть jpg-файл. Если я пытаюсь его открыть (через https) в браузере, то все ОК. И даже пароля никакого не просит. А вот если пытаюсь скачать хотябы тем же Флешгетом, то пишет что пароль неверный. Спросил у своего системного администратора, она сказал что пароля нет. Это как? Использовать Username:= 'Anonymous', Password:= '' ?

Автор: Alex 5.9.2005, 07:59
Цитата(Poseidon @ 5.9.2005, 01:26)
А что дальше-то делать?

Посмотреть, что за компоненты ты кинул и попытаться хоть немного подумать, а не ждать готового решения. И когда все это произойдет, то сделать поиск по форуму и найти хотя бы вот эту тему http://forum.vingrad.ru/index.php?showtopic=48563&hl=idhttp Порты не забудь нужные прописать в соответствии с первой темой и dll скачать

Автор: Poseidon 5.9.2005, 19:50
Цитата(Alex @ 5.9.2005, 07:59)
а не ждать готового решения
Вот так всегда, сам помогаешь, нередко даешь готовые решения. А как каснулось, так тебе никто дать решение не хочет. Понятное дело, что нужно разбираться. Я просто думал у кого-то уже есть это самое готовое решения. Лана, буду разбиратся сам.

PS. А ведь в подписи моей правда smile

Автор: Snowy 5.9.2005, 20:02
Готовое решение лежит на сайте Indy.
Скачай Indy Demos.

Автор: Poseidon 5.9.2005, 20:24
Все братья!!! Закачалось! То что хотел, достиг. Сказать "без вашей помощи" язык не повернется. Спасибо.

Отдельное благадарю Snowy, за примеры в той самой теме, на каторую вы меня послали smile
Вот уж действительно, если хочешь что-то сделать, сделай это сам. smile

Автор: Snowy 5.9.2005, 21:08
Цитата(Poseidon @ 5.9.2005, 20:24)
о что хотел, достиг.

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

Автор: Poseidon 5.9.2005, 23:02
Используемые компоненты:
TIdHTTP (вкладка Indy Clients),
TIdSSLIOHandlerSocket (вкладка Indy I/O Handlers),
TButton (для начала загрузки).

В инспекторе обьектов для компонента TIdHTTP устанавливаем:
BoundPort := 443;
IOHandler:= IdSSLIOHandlerSocket1

Скачиваем две библиотеки http://www.intelicom.si/domcms.nsf/b22359a69e6184e185256d07000a3de0/8a3b424f424132d088256f4c0072c460/$FILE/indy_openssl096k.zip и копируем их в папку с программой.


Код
procedure TForm1.Button1Click(Sender: TObject);
const URL = 'https://z53.org/photo/az.jpg'; // файл, каторый качаем
var Stream: TMemoryStream;
begin
Stream:= TMemoryStream.Create;
IdHTTP1.Get(URL,Stream);
Stream.SaveToFile('C:\az.jpg');
Stream.Free;
end;

Автор: Poseidon 7.9.2005, 21:21
А вот и подводные камни.

При беспарольном доступе все работает на ура. Но вот при парольном... smile

В компоненте TIdHTTP добавил:
Request.Username:= 'MyUsername';
Request.Password:= 'MyPassword';

А выдает "Socket error # 10048 Adress already in use."

Ничего понять не могу, идеи кончились smile
Добавлено @ 21:22
Забыл добавить, что при заходе через браузер (IE) при этих же Имени и Пароле все ОК.

Вот такие пираги smile

Автор: Snowy 7.9.2005, 21:34
BasicAuthentication в true ставил?

Добавлено @ 21:42
Цитата
Error 10048 (Address already in use) Binding Socket
    Означает что программа пытается инициализировать работу с сетью, и на этом этапе у неё происходит сбой, тк адрес уже заняла другая программа.

Цитата
(10048)
Address already in use.
Typically, only one usage of each socket address (protocol/IP address/port)
is permitted. This error occurs if an application attempts to bind a socket
to an IP address/port that has already been used for an existing socket, or
a socket that wasn't closed properly, or one that is still in the process of
closing. For server applications that need to bind multiple sockets to the
same port number, consider using setsockopt(SO_REUSEADDR). Client
applications usually need not call bind at all-connect chooses an unused
port automatically. When bind is called with a wildcard address (involving
ADDR_ANY), a WSAEADDRINUSE error could be delayed until the specific address
is committed. This could happen with a call to another function later,
including connect, listen, WSAConnect, or WSAJoinLeaf.


IMHO стоит создавать все контролы динамически и убивать после использования.

Автор: Poseidon 8.9.2005, 16:32
Цитата(Snowy @ 7.9.2005, 21:34)
IMHO стоит создавать все контролы динамически и убивать после использования.
Спасибо Snowy. Вот сделал:

Код
procedure TForm1.Button1Click(Sender: TObject);
const URL = 'https://z53.org/poseidon/pos.jpg';
var
IdHTTP: TIdHTTP;
IdSSLIOHandlerSocket: TIdSSLIOHandlerSocket;
Stream: TMemoryStream;
begin
IdHTTP:= TIdHTTP.Create(Application);
IdSSLIOHandlerSocket:= TIdSSLIOHandlerSocket.Create(Application);
Stream:= TMemoryStream.Create;

IdHTTP.BoundPort:= 443;
IdHTTP.IOHandler:= IdSSLIOHandlerSocket;
IdHTTP.Request.Username:= 'poseidon';
IdHTTP.Request.Password:='Password';
IdHTTP.Request.BasicAuthentication:= true;

IdHTTP.Get(URL,Stream);
Stream.SaveToFile('C:\a.jpg');

Stream.Free;
IdHTTP.Free;
IdSSLIOHandlerSocket.Free;

ShowMessage('OK');
end;


И вот что интересно. При первой попытке скачать все проходит. Но при повторе та же ошибка. Посмотрел в фаирволе, порт 443 никем не занят. Так что же мешает проге соединится заново? Причем, если подождать минуту-две, то все опять ОК. Это что, Винда не дает заново соединится? Так а как это можно обойти?

Автор: Snowy 8.9.2005, 16:52
Правильно будет:
Код

  IdHTTP:= TIdHTTP.Create(Application);    
  IdSSLIOHandlerSocket:= TIdSSLIOHandlerSocket.Create(IdHTTP);

И дестроить IdSSLIOHandlerSocket не нужно.
Попробуй так. Я пока поковыряю исходняки Indy.

Автор: Poseidon 8.9.2005, 17:15
Вот ***!!! smile Обьясните тупому Посейдону в чем разница между IdHTTP.BoundPort и IdHTTP.Port
Изменил в своем коде и все пашет на ура. Матов не хватает smile

Snowy, отдельное спасибо за поддержку smile

Автор: Snowy 8.9.2005, 17:20
Цитата(Poseidon @ 8.9.2005, 17:15)
бьясните тупому Посейдону в чем разница между IdHTTP.BoundPort и IdHTTP.Port

Ух. Я и не заметил, что ты BoundPort поставил, вместо порт smile
BoundPort не трогай - он выбирается динамически, если не укажешь иного.
Это порт на твоей машине, а не на удаленной.
Поэтому сокет и глючил.
Добавлено @ 17:23
BoundPort обычно выбирается автоматом из свободных из диапазона BoudMin и BoundMax.
Я не знаю, по каким причинам он не освобождался в данном примере, но факт в том, что порт указан фиксировано и автомат поиска свободного был отключен.

Автор: Snowy 8.9.2005, 23:08
Итак получаем на выходе готовое решение.

Получить файл по HTTPS:
Код

uses IdHTTP, IdSSLOpenSSL;

function GetSSLHttp(url, user, password, FileName: string;  PortNum: integer=443):boolean;
var
  http: TIdHTTP;
  ssl:  TIdSSLIOHandlerSocket;
  ms:   TMemoryStream;
begin
  http := TIdHTTP.Create(nil);
  ssl := TIdSSLIOHandlerSocket.Create(http);
  ms := TMemoryStream.Create;
  http.Port := PortNum;
  http.IOHandler := ssl;
  http.Request.Username := user;
  http.Request.Password:=password;
  http.Request.BasicAuthentication := true;
  try
    http.Get(url, ms);
    result:=true;
  ms.SaveToFile(FileName);
  except
    result :=false;
  end;
  ms.Free;
  http.Free;
end;

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)