Reputation: 13454
I've checked out the usefule link how to download a file from internet using Delphi and my question related but I would appreciate a pointer to get started. I need to be able to copy all files in a web server folder down to a local folder. I wont know how many files there are, or indeed whether there is an internet connection. Are there component(s) that would help me please? Or can I use Windows API? Thanks Brian
Upvotes: 2
Views: 4738
Reputation: 24483
I'd start with this answer and in stead of putting the output result in a string, write the buffer to a TFileStream.
WinInet is really nice, as it respects the proxy settings the user set on Windows (so you don't have to put a lot of work into how to make that configurable with Indy).
Edit:
I refactored that answer a bit to download binary files.
Since it uses WinInet you can use it for both ftp and http download (yes, I checked that it did).
You can extend this to use FtpFindFirstFile/InternetFindNextFile and read a whole bunch of files.
unit DownloadBinaryFileUnit;
interface
uses
Classes,
WinInet;
type
TWinInet = class
strict protected
class procedure ReadBinaryFileResponse(const UrlHandle: HINTERNET; const LocalFileName: string); static;
class procedure ReadResponse(const UrlHandle: HINTERNET; const ContentStream: TStream);
public
class procedure DownloadBinaryFile(const UserAgent, Url, LocalFileName: string); overload; static;
end;
implementation
uses
SysUtils,
Variants,
Windows,
IOUtils;
class procedure TWinInet.DownloadBinaryFile(const UserAgent, Url, LocalFileName: string);
var
InternetHandle: HINTERNET;
UrlHandle: HINTERNET;
begin
InternetHandle := InternetOpen(PChar(UserAgent), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
try
UrlHandle := InternetOpenUrl(InternetHandle, PChar(Url), nil, 0, 0, 0);
try
ReadBinaryFileResponse(UrlHandle, LocalFileName);
finally
InternetCloseHandle(UrlHandle);
end;
finally
InternetCloseHandle(InternetHandle);
end;
end;
class procedure TWinInet.ReadBinaryFileResponse(const UrlHandle: HINTERNET; const LocalFileName: string);
var
ContentStream: TFileStream;
begin
ContentStream := TFile.Create(LocalFileName);
try
ReadResponse(UrlHandle, ContentStream);
finally
ContentStream.Free;
end;
end;
class procedure TWinInet.ReadResponse(const UrlHandle: HINTERNET; const ContentStream: TStream);
var
Buffer: array[0..1023] of Byte;
BytesRead: Cardinal;
begin
repeat
InternetReadFile(UrlHandle, @Buffer, SizeOf(Buffer), BytesRead);
ContentStream.Write(Buffer, BytesRead);
until BytesRead = 0;
end;
end.
--jeroen
Upvotes: 2
Reputation: 36654
If the HTTP server supports WebDAV, you can simply map a network drive and use file system commands to iterate the server side files.
If your application has no permissions to create network drives, one of the existing WebDAV client implementations for Delphi can be used instead.
Upvotes: 1
Reputation: 596216
If, and only if, the web server is configured to allow Directory Browsing (most servers do not), then you can request the URL of the folder and the web server will send back an HTML file containing the directory listing. You would then have to parse the HTML to determine the individual filenames, and then request their URLs one at a time.
If Directory Browsing is disabled, then there is no way to do what you are asking for without knowing the filenames ahead of time. Using FTP is a better choice, if available.
Upvotes: 3
Reputation: 36840
Since HTTP doesn't actually handle a concept as a folder of files, you should check if FTP is available on the server.
Still, if you're sure you're stuck to HTTP, you'll first have to find a way to collect a list of (full) URL's for all the files, and download them one by one using one of the techniques.
(You could then try to download more than one simultaneously, but ample experience teaches that bandwith is just that: bandwidth, and downloading a number of files one by one or all together takes about just as long.)
Upvotes: 0