如何保持嵌入式浏览器提示在哪里保存下载的文件? [英] How do I keep an embedded browser from prompting where to save a downloaded file?

查看:341
本文介绍了如何保持嵌入式浏览器提示在哪里保存下载的文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在程序中点击下载按钮后下载文件,因此无需知道下载文件的URL。

How to down load a file after clicking a download button programatically, and therefore not needing to know the url for the downloading file.

文件下载完成后提示出现并询问您是否要保存文件,按yes后,另一个提示会询问您要保存文件的位置。所以,文件首先被下载,也许在某个地方的缓冲区中,在初始下载之后出现提示。

After a file has downloaded a prompt comes up and asks if you'd like to save the file, after pressing 'yes' another prompt asks where you'd like to save the file. So, the file is downloaded first, maybe into a buffer somewhere, after the initial download, the prompts appear.

所以,一旦点击按钮,如何捕获下载流并将其另存为某个文件,而不显示弹出提示?

So, once the button is clicked how do you capture the downloading stream and save it as a file somewhere, without the popup prompts appearing?

(任何单击按钮的方法都可以,以下应该是正常的。)

(Any method for clicking a button would be fine, the following should be fine.)

procedure TForm1.Button1Click(Sender: TObject);
var
  x: integer;
  ovLinks: OleVariant;
begin
  WebBrowser1.Navigate('The web page');
  //wait for page to down load
  ovLinks := WebBrowser1.OleObject.Document.all.tags('A');
  if ovLinks.Length > 0 then
  begin
    for x := 0 to ovLinks.Length-1 do
      begin
        if Pos('id of button', ovLinks.Item(x).id) > 0 then
        //or if Pos('href of button', ovLinks.Item(x).href) > 0 then
        begin
          ovLinks.Item(x).click;
          Break;
        end;
      end;
  end;
end;

此问题的原因是:无法始终找到文件的URL。
例如:在此网站,我找不到网址编程,但是按下导出按钮后,使用IE,该文件被下载到'临时Internet文件'文件夹。在IE的Internet临时文件文件夹中,它有一列Internet地址,显示该URL。但是在Chrome中没有这样的数据存在。但是,在这个网站中,我可以通过编程方式找到该URL,但是当我下载文件,按这里,文件不会出现在IE的Internet临时文件夹中。对于其他网站,可以在该文件夹中找到该URL,并通过编程方式找到该URL,但是在其他站点中,无法找到该URL。

The reason for this question is: the url of a file can not always be found. Eg: At this web site, I couldn't find the url programatically but after pressing the export button, using IE, the file was download into the 'Temporary Internet Files' folder. In the IE 'Temporary Internet Files' folder it has a column 'Internet adress' which shows the url. But in Chrome no such data exists. BUT, at this web site, I can find the url programatically, but when I download the file, by pressing 'here', the file doesn't appear in the IE 'Temporary Internet Files' folder. For other websites, the url can be found in the folder and by finding it programatically, but at other sites the url can not be found either way.

推荐答案

实现 IDownloadManager 接口与其 下载 方法到您的Web浏览器控件你可以简单地控制你需要的东西。 下载 方法被调用,只要你要下载一个文件(只有当保存为对话框弹出)。

Implement the IDownloadManager interface with its Download method to your web browser control and you can simply control what you need. The Download method is called whenever you're going to download a file (only when the save as dialog pops up).

<强> 1。嵌入式Web浏览器

1. Embedded Web Browser

您可以使用 嵌入式Web浏览器 控件具有此接口已实现,并触发 OnFileDownload 这与 TWebBrowser 中的同一个命名事件不同。请参阅 此线程 如何使用它。

You can use the Embedded Web Browser control which has this interface already implemented and which fires the OnFileDownload that is different from the same named event in TWebBrowser. See for instance this thread on how to use it.

2。自己动手

2. Do it yourself

另一种选择是您可以将其实现为 TWebBrowser 你自己在下面的例子中,我使用了插入的类只是为了显示原理,但它很容易将其作为组件包装(这就是为什么我已经发布了 OnBeforeFileDownload 发布) 。

Another option is that you can implement it to TWebBrowser by yourself. In the following example I've used interposed class just for showing the principle, but it's very easy to wrap it as a component (that's why I've made the OnBeforeFileDownload published).

2.1。 OnBeforeFileDownload事件

2.1. OnBeforeFileDownload event

此插入类中 TWebBrowser 的唯一扩展名是 OnBeforeFileDownload 事件将在文件下载时触发​​(在保存为对话框弹出之前,而不是 OnFileDownload 事件,而不是下载文档时)。如果您不会为其编写事件处理程序,则Web浏览器控件的行为将如前所述(显示为另存为对话框)。如果您写入事件处理程序并将False返回给其允许的声明参数,则文件保存将被取消。如果您将True设置为允许参数(默认为什么),则将显示另存为对话框。
请注意,如果您通过将允许设置为False来取消下载,则需要自己下载该文件(正如我在本例中同步使用Indy) 。为此,有 FileSource 常量参数,其中包含下载的文件URL。以下是事件参数概述:

The only extension to TWebBrowser in this interposed class is the OnBeforeFileDownload event which fires when the file is going to be downloaded (before save as dialog pops up, but instead of the OnFileDownload event, not when the document itself is downloaded). If you won't write the event handler for it, the web browser control will behave as before (showing a save as dialog). If you write the event handler and return False to its Allowed declared parameter, the file saving will be cancelled. If you return True to the Allowed parameter (what is by default), the save as dialog will be shown. Note that if you cancel downloading by setting Allowed to False, you'll need to download the file by yourself (as I did synchronously using Indy in this example). For this purpose there's the FileSource constant parameter, which contains the downloaded file URL. Here is the event parameters overview:


  • 发件人(TObject) - 事件发件人

  • FileSource(WideString ) - 源文件URL

  • 允许(布尔) - 声明的布尔参数,它决定是否允许文件下载(默认值为True)

2.2。 IDownloadManager实现

2.2. IDownloadManager implementation

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  StdCtrls, OleServer, OleCtrls, Dialogs, ActiveX, MSHTML, UrlMon, SHDocVw,
  IdHTTP;

const
  IID_IDownloadManager: TGUID = '{988934A4-064B-11D3-BB80-00104B35E7F9}';
  SID_SDownloadManager: TGUID = '{988934A4-064B-11D3-BB80-00104B35E7F9}';

type
  IDownloadManager = interface(IUnknown)
    ['{988934A4-064B-11D3-BB80-00104B35E7F9}']
    function Download(pmk: IMoniker; pbc: IBindCtx; dwBindVerb: DWORD;
      grfBINDF: DWORD; pBindInfo: PBindInfo; pszHeaders: PWideChar;
      pszRedir: PWideChar; uiCP: UINT): HRESULT; stdcall;
  end;
  TBeforeFileDownloadEvent = procedure(Sender: TObject; const FileSource: WideString;
    var Allowed: Boolean) of object;
  TWebBrowser = class(SHDocVw.TWebBrowser, IServiceProvider, IDownloadManager)
  private
    FFileSource: WideString;
    FOnBeforeFileDownload: TBeforeFileDownloadEvent;
    function QueryService(const rsid, iid: TGUID; out Obj): HRESULT; stdcall;
    function Download(pmk: IMoniker; pbc: IBindCtx; dwBindVerb: DWORD;
      grfBINDF: DWORD; pBindInfo: PBindInfo; pszHeaders: PWideChar;
      pszRedir: PWideChar; uiCP: UINT): HRESULT; stdcall;
  protected
    procedure InvokeEvent(ADispID: TDispID; var AParams: TDispParams); override;
  published
    property OnBeforeFileDownload: TBeforeFileDownloadEvent read FOnBeforeFileDownload write FOnBeforeFileDownload;
  end;

type
  TForm1 = class(TForm)
    Button1: TButton;
    WebBrowser1: TWebBrowser;
    FileSourceLabel: TLabel;
    FileSourceEdit: TEdit;
    ShowDialogCheckBox: TCheckBox;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    procedure BeforeFileDownload(Sender: TObject; const FileSource: WideString;
      var Allowed: Boolean);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TWebBrowser }

function TWebBrowser.Download(pmk: IMoniker; pbc: IBindCtx; dwBindVerb,
  grfBINDF: DWORD; pBindInfo: PBindInfo; pszHeaders, pszRedir: PWideChar;
  uiCP: UINT): HRESULT;
var
  Allowed: Boolean;
begin
  Result := E_NOTIMPL;
  if Assigned(FOnBeforeFileDownload) then
  begin
    Allowed := True;
    if pszRedir <> '' then
      FFileSource := pszRedir;
    FOnBeforeFileDownload(Self, FFileSource, Allowed);
    if not Allowed then
      Result := S_OK;
  end;
end;

procedure TWebBrowser.InvokeEvent(ADispID: TDispID; var AParams: TDispParams);
begin
  inherited;
  // DispID 250 is the BeforeNavigate2 dispinterface and to the FFileSource here
  // is stored the URL parameter (for cases, when the IDownloadManager::Download
  // won't redirect the URL and pass empty string to the pszRedir)
  if ADispID = 250 then
    FFileSource := OleVariant(AParams.rgvarg^[5]);
end;

function TWebBrowser.QueryService(const rsid, iid: TGUID; out Obj): HRESULT;
begin
  Result := E_NOINTERFACE;
  Pointer(Obj) := nil;
  if Assigned(FOnBeforeFileDownload) and IsEqualCLSID(rsid, SID_SDownloadManager) and
    IsEqualIID(iid, IID_IDownloadManager) then
  begin
    if Succeeded(QueryInterface(IID_IDownloadManager, Obj)) and
      Assigned(Pointer(Obj))
    then
      Result := S_OK;
  end;
end;

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
  HTMLWindow: IHTMLWindow2;
  HTMLDocument: IHTMLDocument2;
begin
  WebBrowser1.Navigate('http://financials.morningstar.com/income-statement/is.html?t=AAPL&ops=clear');
  while WebBrowser1.ReadyState <> READYSTATE_COMPLETE do
    Application.ProcessMessages;

  HTMLDocument := WebBrowser1.Document as IHTMLDocument2;
  if not Assigned(HTMLDocument) then
    Exit;
  HTMLWindow := HTMLDocument.parentWindow;
  if Assigned(HTMLWindow) then
  try
    HTMLWindow.execScript('SRT_stocFund.Export()', 'JavaScript');
  except
    on E: Exception do
      ShowMessage(E.Message);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ReportMemoryLeaksOnShutdown := True;
  WebBrowser1.OnBeforeFileDownload := BeforeFileDownload;
end;

procedure TForm1.BeforeFileDownload(Sender: TObject; const FileSource: WideString;
  var Allowed: Boolean);
var
  IdHTTP: TIdHTTP;
  FileTarget: string;
  FileStream: TMemoryStream;
begin
  FileSourceEdit.Text := FileSource;
  Allowed := ShowDialogCheckBox.Checked;
  if not Allowed then
  try
    IdHTTP := TIdHTTP.Create(nil);
    try
      FileStream := TMemoryStream.Create;
      try
        IdHTTP.HandleRedirects := True;
        IdHTTP.Get(FileSource, FileStream);
        FileTarget := IdHTTP.URL.Document;
        if FileTarget = '' then
          FileTarget := 'File';
        FileTarget := ExtractFilePath(ParamStr(0)) + FileTarget;
        FileStream.SaveToFile(FileTarget);
      finally
        FileStream.Free;
      end;
    finally
      IdHTTP.Free;
    end;
    ShowMessage('Downloading finished! File has been saved as:' + sLineBreak +
      FileTarget);
  except
    on E: Exception do
      ShowMessage(E.Message);
  end;
end;

end.

2.3。 IDownloadManager项目

2.3. IDownloadManager project

您可以下载上述代码(以Delphi 2009编写)作为一个完整的项目 从这里

You can download the above code (written in Delphi 2009) as a complete project from here.

这篇关于如何保持嵌入式浏览器提示在哪里保存下载的文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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