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
-
This depends on the web server. In the general case, this isn't possible at all, I think. You could use FTP, though, rather than HTTP. Then it would be easy. – Andreas Rejbrand Jan 06 '11 at 00:48
-
possible duplicate of [download a folder from server to local host...](http://stackoverflow.com/questions/2043250/download-a-folder-from-server-to-local-host) – Eugene Mayevski 'Callback Jan 06 '11 at 06:33
-
@Andreas: It will be FTP then! Could you point me at the relevant Delphi component(s) / example? Many Thanks. – Brian Frost Jan 06 '11 at 09:28
-
@Eugene: I cant see how that topic helps me with query. – Brian Frost Jan 06 '11 at 09:28
-
that is a duplicate question of yours. It doesn't "help" - it's a duplicate. The question has been discussed before with conclusion that this can not be done. And the answer remains the same. – Eugene Mayevski 'Callback Jan 06 '11 at 09:33
4 Answers
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.

- 555,201
- 31
- 458
- 770
-
Thanks. I'm very happy to use FTP. Can you suggest how to do this? – Brian Frost Jan 06 '11 at 09:26
-
You can use the same code that Jeroen Pluimers showed. The WinInet API works for FTP as well as HTTP. Just use an FTP URL instead of an HTTP URL. The WinInet API also has some FTP-specific functions available, whereas the ones you are using right now are more general-purpose for multiple protocols. – Remy Lebeau Jan 06 '11 at 21:10
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

- 1
- 1

- 23,965
- 9
- 74
- 154
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.

- 36,362
- 28
- 176
- 378
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.)

- 35,982
- 11
- 45
- 67