An answer to this question showed how easy it is to use WinHTTP via Type Library imports in delphi.
I imported the type library for WinHTTP, and then tried to write a File Download helper function using that api. Here's how far I got:
I can't seem to figure out how to save the IWinHttpRequest.ResponseStream (declared as OleVariant in the TLB file) as Stream, to disk.
// IWinHttpRequest is defined by importing type library of WinHTTP.
// Microsoft WinHTTP Services, version 5.1 (Version 5.1) C:\Windows\system32\winhttp.dll
function Download(const url, filename: String): Boolean;
var
http: IWinHttpRequest;
wUrl: WideString;
fs:TFileStream;
FileStream:IStream;
sz,rd,wr:Int64;
begin
try
wUrl := url;
http := CoWinHttpRequest.Create;
http.open('GET', wurl, False);
http.send(EmptyParam);
FStatus := http.status; // 200=OK!
result := FStatus=200;
if result then
begin
fs := TFileStream.Create(filename, fmCreate, fmShareExclusive );
try
FileStream := TStreamAdapter.Create(fs, soReference) as IStream;
sz := http.ResponseStream.Size;
http.ResponseStream.CopyTo(FileStream,sz,rd,wr);
finally
FileStream := nil;
fs.Free;
end;
end;
except
result := false;
// do not raise exceptions.
end;
end;
Excerpt from WinHTTP_TLB.pas:
IWinHttpRequest = interface(IDispatch)
['{016FE2EC-B2C8-45F8-B23B-39E53A75396B}']
......
property ResponseStream: OleVariant read Get_ResponseStream;
Update: I now get a runtime exception about ole variants, at the call to http.ResponseStream.CopyTo(...)
EOleError 'Variant does not reference an automation object'.
Warren, you must use the AxCtrls.TOleStream
class to comunicate the response stream with the Classes.TFileStream
something like this
IWinHttpRequest.ResponseStream -> TOleStream -> TFileStream
Check this sample code
{$APPTYPE CONSOLE}
uses
Variants,
ActiveX,
Classes,
AxCtrls,
WinHttp_TLB,
SysUtils;
function Download(const url, filename: String): Boolean;
var
http: IWinHttpRequest;
wUrl: WideString;
fs:TFileStream;
HttpStream :IStream;
sz,rd,wr:Int64;
FStatus : Integer;
OleStream: TOleStream;
begin
try
wUrl := url;
http := CoWinHttpRequest.Create;
http.open('GET', wurl, False);
http.send(EmptyParam);
FStatus := http.status; // 200=OK!
result := FStatus=200;
if result then
begin
HttpStream:=IUnknown(http.ResponseStream) as IStream;
OleStream:= TOleStream.Create(HttpStream);
try
fs:= TFileStream.Create(FileName, fmCreate);
try
OleStream.Position:= 0;
fs.CopyFrom(OleStream, OleStream.Size);
finally
fs.Free;
end;
finally
OleStream.Free;
end;
end;
except
result := false;
// do not raise exceptions.
end;
end;
begin
try
Download('http://foo.html','C:\Foo\anyfile.foo');
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
来源:https://stackoverflow.com/questions/6795915/save-a-file-downloaded-via-winhttp-to-disk-using-delphi-xe