PDA

Просмотр полной версии : Загрузка файла из инета.


Proger10
26.11.2009, 17:26
Вопрос конечно не первый раз задается, но что нашел или не работает или еше что-нибудь. Ну так как сделать сабж, IdHTTP не предлагать!!

Nightmarе
26.11.2009, 17:36
// Закачка файла на комп
function DownloadToComp(const fileURL, FileName: string): boolean;
const
BufferSize = 1024;
var
hSession, hURL: HInternet;
Buffer: array[1..BufferSize] of Byte;
BufferLen: DWORD;
f: file;
begin
Result := False;
hSession := InternetOpen(nil, INTERNET_OPEN_TYPE_DIRECT, nil, nil, 0);
try
hURL := InternetOpenURL(hSession, PChar(fileURL), nil, 0, 0, 0);
try
AssignFile(f, FileName);
Rewrite(f,1);
repeat
InternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen);
BlockWrite(f, Buffer, BufferLen);
until
BufferLen = 0;
CloseFile(f);
Result := True;
finally
InternetCloseHandle(hURL);
end;
finally
InternetCloseHandle(hSession);
end;
end;

вызываешь так:
DownloadToComp('http://lol.ru/file.exe','C:\file.exe');
И не забудь в uses вписать APIшку WinInet

Ins3t
27.11.2009, 00:35
2Nightmarе, не проще ли воспользоваться API функцией UrlDownloadToFile()

Nightmarе
27.11.2009, 06:14
можно и так, но антивири будут ругаться на апишку urlmon.
вот подумай ©

Proger10
27.11.2009, 15:45
2Ins3t, в моем случае не проще.
2Nightmarе, спасибо, то что надо!
А еше некто не поделится как проверить наличие возможности подключения к серверу по определенному порту(80)?? Желетельно через WinInet.

Nightmarе
27.11.2009, 20:20
вот как раз через WinInet помоему и невозможно (хотя скорее всего нагло вру), ибо там функция проверки DialUp соединения, а если у юзверя через сетевую карту, то он активность всегда будет показывть онлайн.

Proger10
28.11.2009, 10:55
Вот попытался сделать через winsAck:

procedure TForm1.Button1Click(Sender: TObject);
var
WSAData: TWSAData;
S: TSocket;
SockAddrIn: TSockAddr;
Timeout: TTimeVal;
begin
if WSAStartup($101, WSAData)<>0 then
exit;
SockAddrIn.sin_family:=AF_INET;
SockAddrIn.sin_addr.S_addr:=inet_addr(pchar(Edit1. Text));
S:=socket(AF_INET,SOCK_STREAM,0);
if S=INVALID_SOCKET then
Exit;
Timeout.tv_usec := 0;
Timeout.tv_sec := 1000;
setsockopt(S, SOL_SOCKET, SO_RCVTIMEO, @Timeout, sizeof(TTimeVal));
SockAddrIn.sin_port:=htons(StrToInt(Edit2.Text));
if connect(S, SockAddrIn, sizeof(SockAddrIn))=0 Then
begin
ShowMessage('Тут кто-то есть!');
end
else
begin
ShowMessage('Никого нет!');
end;
end;

Если на порте кто-то есть, то все отлично программа вполне быстро сообщает об этом, а если там никого нет, то проходит секунд десять до соответствующего сообшения, попытался добаввить таймаут - нифига не получилось.. Что не так??

Proger10
29.11.2009, 09:19
Где то прочитал что в Индюке эта проблема решается с помощю второго потока, сделал - вроде получилось.
Unit1:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, WinSock, ExtCtrls, Unit2;

type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
Edit2: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
CanConnect: boolean;
CanConnectChanged: boolean;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
begin
CanConnect:=False;
Ping:= TPingThread.Create(True);
Ping.IP:=Edit1.Text;
Ping.Port:=StrToInt(Edit2.Text);
Ping.Suspended:=False;
for I := 1 to 1000 do
begin
Sleep(1);
Application.ProcessMessages;
end;
if not CanConnectChanged then
begin
Ping.Suspended:=True;
CanConnect:=False;
end;
if Canconnect then
ShowMessage('We are TRUE!!')
else
ShowMessage('We are FALSE!!');
end;


end.
Unit2:
unit Unit2;

interface

uses
Classes, WinSock;

type
TPingThread = class(TThread)
IP: string;
Port: integer;
private
{ Private declarations }
protected
procedure Execute; override;
end;

var
Ping: TPingThread;

implementation

uses Unit1;

{ Important: Methods and properties of objects in visual components can only be
used in a method called using Synchronize, for example,

Synchronize(UpdateCaption);

and UpdateCaption could look like,

procedure TPingThread.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }

{ TPingThread }

procedure TPingThread.Execute;
var
WSAData: TWSAData;
S: TSocket;
SockAddrIn: TSockAddr;
begin
if WSAStartup($101, WSAData)<>0 then
exit;
SockAddrIn.sin_family:=PF_INET;
SockAddrIn.sin_addr.S_addr:=inet_addr(pchar(IP));
S:=socket(AF_INET,SOCK_STREAM,0);
if S=INVALID_SOCKET then
Exit;
SockAddrIn.sin_port:=htons(Port);
if connect(S, SockAddrIn, sizeof(SockAddrIn))=0 Then
begin
Form1.CanConnectChanged:=True;
Form1.CanConnect:=True;
end
else
begin
Form1.CanConnectChanged:=True;
Form1.CanConnect:=False;
end;
end;

end.
Низнаю правельно ли так делать!

Nightmarе
29.11.2009, 13:32
Вот тебе правильный и рабочий код на индюке:

В uses добавляешь: IdMultipartFormData, IdHTTP
А далее функция:
function DownloadToComp(const fileURL, FileName: string):string;
var
postdownloadhttp:TidHTTP;
d:TIdMultiPartFormDataStream;
begin
postdownloadhttp:=TidHTTP.create(nil);
d:=TIdMultiPartFormDataStream.Create;
d.AddFile('userfile',FileName,'file');
try
postdownloadhttp.Post(fileURL+'?',d);
d.Free;
except
postdownloadhttp.Disconnect;
d.Free;
end;
postdownloadhttp.Free;
end;

работает по аналогии с вин инетом, только через пернатого.