Delphi- downloading files from the Internet using sockets
I've tried Synapse, Indy, and ICS and I'm not happy with them. I want to download multiple files in multiple parts at the same time, resume support, gzip encoded files, cookies, write to websites using POST and so on. So I think I'll just write with sockets. But I can see that Delphi has a lot of sockets: TTcpClient, TRawSocket, TCGIRequest, TClientSocket, and so on. They are all poorly documented - it is very difficult to find examples of use. I tried using TTcpClient but sometimes the program freezes and then hits a timeout and I have no idea why. Looks like a problem, waiting for answers. This is of course not a server issue, because I am testing on localhost. What is the best socket for working with HTTP? Something easy to use?
I want to use in both Delphi 7 and XE2. I don't want to use something like WinAPI, so I don't have to deal with PChars and other non-Delphi stuff.
I also think of something like:
1) Exactly what I want - loads multiple parts with progressbars from many files to the same file
OR
2) Something like telnet, so I just write the HTTP commands as strings and I get the byte arrays in reverse order, which I can either convert to strings or save to streams.
source to share
I can't comment on other libraries, but Indy supports everything you ask for.
The component TIdHTTP
can upload files using byte ranges if the server supports it. You can use the method TIdHTTP.Head()
to check if the server is returning a title Accept-Ranges: bytes
for a given url. If so, then you can set the properties TIdHTTP.Request.ContentRangeStart
and TIdHTTP.Request.ContentRangeEnd
to the bytes you want if needed when loading data from that url. To load multiple parts of a resource at the same time, simply execute multiple threads, each with its own component TIdHTTP
, in parallel. You will either have to download multiple chunks to separate the temporary files and then merge them into the final file when finished, or create one pre-defined file and then open multiple objects TFileStream
to it with the desired starting offsets forTIdHTTP
for recording.
TIdHTTP
supports cookies. You can assign a component TIdCookieManager
to a property TIdHTTP.CookieManager
or leave it unassigned and TIdHTTP
will create an object TIdCookieManager
within itself. In any case, also set the property TIdHTTP.AllowCookies
to True.
Login to the site should be done in one of two ways, depending on whether the server is using HTTP authentication or WebForm based authentication:
-
For HTTP authentication, add the desired units
IdAuthentication...
to your clauseuses
likeIdAuthentacationDigest
andIdAuthenticationNTLM
, orIdAllAuthentications
unt to register individual authentication classes withTIdHTTP
and then set theTIdHTTP.Request.UserName
and propertiesTIdHTTP.Request.Password
as needed. If the WebServer requests authentication at the time of the request, itTIdHTTP
will select the appropriate class and use it to log in with the specified credentials. If the server rejects the credentials, an eventTIdHTTP.OnAuthorization
will be fired to give you the opportunity to change the credentials and try again. -
For WebForm authentication, there is a class
TIdMultipartFormDataStream
that can be passed to a methodTIdHTTP.Post()
to host a formatted POST requestmultipart/form-data
.
TIdHTTP
Indy 10 supports gzip files and photo compressed files ( TIdHTTP
Iny 9 and earlier does not support compression). You can assign the TIdZLibCompressorBase
nested component to, for example TIdCompressorZLib
, a property TIdHTTP.Compressor
, and it TIdHTTP
will handle all the details for you, including sending the appropriate request header Accept-Encoding
and validating server Transfer-Encoding
.
TIdHTTP
has OnWorkBegin
, OnWork
and OnWorkEnd
events that can be used for a progress bar, etc. The event OnWorkBegin
has a parameter AWorkCountMax
that defines the total number of bytes transferred, if known, otherwise it will be 0 (HTTP responses that use a header Content-Length
are set accordingly AWorkCountMax
, but HTTP responses that use a header Transfer-Encoding: chunked
will not). The event OnWork
has a parameter AWorkCount
that indicates how many bytes have been transferred so far, regardless of the value AWorkCounMax
.
source to share