使用Delphi XE将通过WinHTTP下载的文件保存到磁盘 [英] Save a file downloaded via WinHTTP to disk, using Delphi XE

查看:370
本文介绍了使用Delphi XE将通过WinHTTP下载的文件保存到磁盘的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题的答案显示,通过Delphi中的类型库导入使用WinHTTP是多么容易

An answer to this question showed how easy it is to use WinHTTP via Type Library imports in delphi.

我导入了WinHTTP的类型库,然后尝试使用该api编写一个File Download helper函数。这是我有多远:

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:

我似乎无法弄清楚如何将IWinHttpRequest.ResponseStream(在TLB文件中声明为OleVariant)作为Stream保存到磁盘

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;

摘自WinHTTP_TLB.pas:

Excerpt from WinHTTP_TLB.pas:

 IWinHttpRequest = interface(IDispatch)
    ['{016FE2EC-B2C8-45F8-B23B-39E53A75396B}']
    ......
    property ResponseStream: OleVariant read Get_ResponseStream;

更新:我现在得到一个关于ole变体的运行时异常,在调用 http.ResponseStream.CopyTo(...)

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,你必须使用 AxCtrls.TOleStream 类来汇总响应流 Classes.TFileStream

Warren, you must use the AxCtrls.TOleStream class to comunicate the response stream with the Classes.TFileStream

这样的东西

IWinHttpRequest.ResponseStream -> TOleStream -> TFileStream

查看此示例代码

{$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.

这篇关于使用Delphi XE将通过WinHTTP下载的文件保存到磁盘的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆