如何使用 URLOpenStream 函数

 我来答
ahcc08
推荐于2018-04-04 · 知道合伙人软件行家
ahcc08
知道合伙人软件行家
采纳数:11853 获赞数:51941
拥有丰富的软件开发经验。

向TA提问 私信TA
展开全部
URLOpenStream 和 URLDownloadToFile 类似, 都是下载文件的 COM 函数;
前者是下载到 IStream 流, 后者是直接下载到指定路径;
它们都声明在 UrlMon 单元, 本例还要同时 uses ActiveX, 因为要用到 IStream 接口.
function URLOpenStream(
p1: IUnknown; { 接口, 不用它, 给 nil 即可 }
p2: PWideChar; { 要下载的路径 }
p3: DWORD; { 暂未使用的参数, 须是 0 }
p4: IBindStatusCallback { 接口, 下载后的数据得给它要; 我们需要实现它 }
): HResult; stdcall; { 返回 S_OK 表示成功, 本例是使用了 Succeeded 函数判断的 }

IBindStatusCallback 接口有八个方法(或事件), 用到用不到都得给简单实现下;
我们主要实现的是其中的 OnDataAvailable, 因为下载后的数据是通过其 stgmed 参数返回的.

下面是实现及测试代码:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, UrlMon, ActiveX;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
end;

TBindStatusCallback = class(TInterfaceList, IBindStatusCallback)
public
function OnStartBinding(dwReserved: DWORD; pib: IBinding): HResult; stdcall;
function GetPriority(out nPriority): HResult; stdcall;
function OnLowResource(reserved: DWORD): HResult; stdcall;
function OnProgress(ulProgress, ulProgressMax, ulStatusCode: ULONG;
szStatusText: LPCWSTR): HResult; stdcall;
function OnStopBinding(hresult: HResult; szError: LPCWSTR): HResult; stdcall;
function GetBindInfo(out grfBINDF: DWORD; var bindinfo: TBindInfo): HResult; stdcall;
function OnDataAvailable(grfBSCF: DWORD; dwSize: DWORD; formatetc: PFormatEtc;
stgmed: PStgMedium): HResult; stdcall;
function OnObjectAvailable(const iid: TGUID; punk: IUnknown): HResult; stdcall;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
url: string;
MyBindStatusCallback: IBindStatusCallback;
begin
Button1.Caption := '正在下载...';
Button1.Enabled := False;

url := 'http: //xxx';
MyBindStatusCallback := TBindStatusCallback.Create;
if Succeeded(URLOpenStream(nil, PChar(url), 0, MyBindStatusCallback)) then
Button1.Caption := '下载完毕!'
else
Button1.Caption := '下载失败!';

Button1.Enabled := True;
end;

{ TBindStatusCallback }

function TBindStatusCallback.GetBindInfo(out grfBINDF: DWORD;
var bindinfo: TBindInfo): HResult;
begin
Result := S_OK;
end;

function TBindStatusCallback.GetPriority(out nPriority): HResult;
begin
Result := S_OK;
end;

function TBindStatusCallback.OnDataAvailable(grfBSCF, dwSize: DWORD;
formatetc: PFormatEtc; stgmed: PStgMedium): HResult;
var
Stream: IStream;
mem: TMemoryStream;
begin
if dwSize > 0 then
begin
Stream := IStream(stgmed.stm);
mem := TMemoryStream.Create;
mem.SetSize(dwSize);
Stream.Read(mem.Memory, dwSize, nil);
//ShowMessage(IntToStr(mem.Size));
mem.SaveToFile('C:\Temp\PMark_1.rar');
mem.Free;
Result := S_OK;
end else Result := E_ABORT;
end;

function TBindStatusCallback.OnLowResource(reserved: DWORD): HResult;
begin
Result := S_OK;
end;

function TBindStatusCallback.OnObjectAvailable(const iid: TGUID;
punk: IInterface): HResult;
begin
Result := S_OK;
end;

function TBindStatusCallback.OnProgress(ulProgress, ulProgressMax,
ulStatusCode: ULONG; szStatusText: LPCWSTR): HResult;
begin
//如果需要下载进度就在这里写代码
Result := S_OK;
end;

function TBindStatusCallback.OnStartBinding(dwReserved: DWORD;
pib: IBinding): HResult;
begin
Result := S_OK;
end;

function TBindStatusCallback.OnStopBinding(hresult: HResult;
szError: LPCWSTR): HResult;
begin
Result := S_OK;
end;

end.
本回答被网友采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式