Delphi 2006 TWebBrowser中pdfMake下载PDF自动打开的禁用方法
解决TWebBrowser中pdfMake生成PDF后自动打开的问题
嘿,我来帮你搞定这个头疼的问题!首先得搞明白根源:Delphi 2006的TWebBrowser绑定的是IE内核,pdfMake的download()方法在IE环境下的行为和现代浏览器差很多——它会触发IE自带的下载机制,默认就是下载完成自动打开文件,而且下载目录是IE的默认下载文件夹(一般是C:\Users\<你的用户名>\Downloads,你可以去那儿找找之前生成的PDF)。
要解决这个问题,有两个靠谱的方向,我推荐第一个,因为它能完全由你控制流程:
方法1:绕开浏览器下载,手动处理PDF buffer
pdfMake提供了getBuffer()方法,能直接拿到PDF的二进制数据,然后我们让JS调用Delphi的方法来保存文件,彻底绕过IE的自动打开逻辑。
具体步骤:
- 修改你的HTML里的JS代码,把原来的
download()换成调用Delphi的外部方法:
// 替换原来的download()调用 pdfMake.createPdf(docDefinition).getBuffer(function(buffer) { // 调用Delphi注册的方法,把PDF的二进制数据传过去 window.external.SavePdfBuffer(buffer); });
- 在Delphi里给TWebBrowser注册
window.external接口,让JS能调用我们的方法:- 先创建一个实现
IDispatch的类,用来处理JS的调用请求:
- 先创建一个实现
type TWebBrowserExternal = class(TInterfacedObject, IDispatch) private FForm: TForm1; function GetTypeInfoCount(out Count: Integer): HResult; stdcall; function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall; function GetIDsOfNames(const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall; function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall; public constructor Create(AForm: TForm1); end;
- 实现这个类,重点在
Invoke方法里处理SavePdfBuffer的调用,这里我们可以用保存对话框让用户选路径:
constructor TWebBrowserExternal.Create(AForm: TForm1); begin inherited Create; FForm := AForm; end; function TWebBrowserExternal.GetTypeInfoCount(out Count: Integer): HResult; begin Count := 0; Result := S_OK; end; function TWebBrowserExternal.GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; begin Result := E_NOTIMPL; end; function TWebBrowserExternal.GetIDsOfNames(const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; begin Result := DispGetIDsOfNames(IID, Names, NameCount, LocaleID, DispIDs); end; function TWebBrowserExternal.Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; var Buffer: OleVariant; FileStream: TFileStream; SaveDialog: TSaveDialog; begin Result := S_OK; if DispID = 1 then // 对应SavePdfBuffer方法 begin Buffer := TVarData(Params).VArray; // 用保存对话框让用户选择保存位置 SaveDialog := TSaveDialog.Create(FForm); try SaveDialog.Filter := 'PDF文件|*.pdf'; if SaveDialog.Execute then begin FileStream := TFileStream.Create(SaveDialog.FileName, fmCreate); try FileStream.WriteBuffer(Buffer[0], Length(Buffer)); finally FileStream.Free; end; end; finally SaveDialog.Free; end; end else Result := DISP_E_MEMBERNOTFOUND; end;
- 在Form的
OnCreate事件里,把这个外部对象绑定到TWebBrowser上:
procedure TForm1.FormCreate(Sender: TObject); var ExternalObj: IDispatch; begin ExternalObj := TWebBrowserExternal.Create(Self); WebBrowser1.DefaultInterface.SetExternal(ExternalObj); end;
这样处理后,PDF的生成和保存完全由你掌控,不会自动打开,用户还能自己选保存的地方,完美解决问题。
方法2:修改IE的全局下载设置(不推荐)
如果你不想改代码,也可以试试修改IE的默认设置:
- 打开IE浏览器,点右上角的设置→Internet选项→安全→自定义级别
- 在“下载”分类下,把“自动下载文件”改成“禁用”,再把“下载后确认打开”改成“禁用”
但这个方法是全局生效的,会影响所有用IE内核的程序,所以只适合临时测试,不适合作为你的程序解决方案。
内容的提问来源于stack exchange,提问作者Matteo Ballardini
相关产品推荐
相关产品推荐

