You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的自动打开逻辑。

具体步骤:

  1. 修改你的HTML里的JS代码,把原来的download()换成调用Delphi的外部方法:
// 替换原来的download()调用
pdfMake.createPdf(docDefinition).getBuffer(function(buffer) {
  // 调用Delphi注册的方法,把PDF的二进制数据传过去
  window.external.SavePdfBuffer(buffer);
});
  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:17:36