2

プログラムでダウンロード ボタンをクリックした後にファイルをダウンロードする方法。したがって、ダウンロード ファイルの URL を知る必要はありません。

ファイルがダウンロードされた後、プロンプトが表示され、ファイルを保存するかどうかを尋ねられます。「はい」を押すと、別のプロンプトがファイルを保存する場所を尋ねます。そのため、ファイルが最初にダウンロードされ、おそらくどこかのバッファにダウンロードされ、最初のダウンロード後にプロンプ​​トが表示されます。

では、ボタンがクリックされたら、ポップアップ プロンプトが表示されずに、ダウンロード ストリームをキャプチャしてファイルとしてどこかに保存するにはどうすればよいでしょうか。

(ボタンをクリックする方法は何でも構いませんが、次の方法でも問題ありません。)

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 が常に見つかるとは限らないためです。例: このWeb サイトでは、プログラムで URL を見つけることができませんでしたが、IE を使用してエクスポート ボタンを押した後、ファイルは「Temporary Internet Files」フォルダにダウンロードされました。IE の「Temporary Internet Files」フォルダには、URL を示す「インターネット アドレス」列があります。しかし、Chrome にはそのようなデータは存在しません。しかし、このWeb サイトでは、プログラムで URL を見つけることができますが、「ここ」を押してファイルをダウンロードすると、IE の「Temporary Internet Files」フォルダにファイルが表示されません。他の Web サイトの場合、url はフォルダー内でプログラムで検索することによって見つけることができますが、他のサイトではどちらの方法でも URL を見つけることができません。

4

2 に答える 2

9

IDownloadManagerメソッドを使用してインターフェイスをWeb ブラウザー コントロールに実装するとDownload、必要なものを簡単に制御できます。このDownloadメソッドは、ファイルをダウンロードするときはいつでも呼び出されます (名前を付けて保存ダイアログがポップアップする場合のみ)。

1. 組み込み Web ブラウザ

Embedded Web Browserこのインターフェイスがすでに実装されていてOnFileDownload、 の同じ名前のイベントとは異なるを起動するコントロールを使用できますTWebBrowser。たとえばthis thread、それを使用する方法を参照してください。

2.自分でやる

別のオプションは、自分で実装できることですTWebBrowser。次の例では、原則を示すためだけに挿入クラスを使用しましたが、コンポーネントとしてラップするのは非常に簡単です (これが、OnBeforeFileDownload公開した理由です)。

2.1. OnBeforeFileDownload イベント

TWebBrowserこの挿入されたクラスの唯一の拡張機能はOnBeforeFileDownload、ファイルがダウンロードされるときに発生するイベントです ([名前を付けて保存] ダイアログがポップアップする前ですがOnFileDownload、ドキュメント自体がダウンロードされたときではなく、イベントの代わりに発生します)。イベント ハンドラーを記述しない場合、Web ブラウザー コントロールは以前と同じように動作します (名前を付けて保存ダイアログを表示します)。イベント ハンドラを記述し、Allowed宣言されたパラメータに False を返すと、ファイルの保存がキャンセルされます。パラメータに True を返すとAllowed(既定値)、名前を付けて保存ダイアログが表示されます。AllowedFalse に設定してダウンロードをキャンセルした場合は、自分でファイルをダウンロードする必要があることに注意してください (この例では Indy を使用して同期的に行ったように)。この目的のために、FileSourceダウンロードしたファイルの URL を含む定数パラメーター。イベント パラメータの概要は次のとおりです。

  • Sender (TObject) - イベントの送信者
  • FileSource (WideString) - ソース ファイルの URL
  • Allowed (ブール値) - ファイルのダウンロードを許可するかどうかを決定する、宣言されたブール値パラメーター (デフォルト値は True)

2.2. IDownloadManager の実装

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 プロジェクト

上記のコード (Delphi 2009 で記述) は、完全なプロジェクトとしてダウンロードできますfrom here

于 2012-11-15T00:08:25.197 に答える
0

これが必要な場所に到達するかどうかはわかりませんが、有望なようです。ここにある TWebBrowser (「Microsoft Internet Controls バージョン 1.1」からエクスポート) では、OnBeforeNavigate2 イベントを使用して、Web ブラウザが処理するすべての URL を監視できます。そこから発生する問題は、何をする必要があるかを判断し、URL を取得して、それを自分で処理することです。これは、あなたが提示した最初の Web サイトのコントロールで 5 分間遊んだ短い例です。

procedure TForm1.WebBrowser1BeforeNavigate2(Sender: TObject;
     pDisp: IDispatch; var URL, Flags, TargetFrameName, PostData,
     Headers: OleVariant; var Cancel: WordBool);
  begin
    Edit1.Text := String(URL);
    if Pos('CSV', Edit1.Text) > 0 then
      Cancel := true;
  end;

ご覧のとおり、多くのパラメーターがあり、それらが何を意味するかを確認するにはドキュメントを見つける必要があります。しかし、私の短い例では、ナビゲートされた URL を Edit1.Text に配置しています (実際に何が起こっているのかを本当に見たい場合は、おそらく TMemo の方が適しています)。あなたの例を考えると、それが直接ダウンロードされたファイルであることを示すものは実際には何もありませんが、上記のコードを使用して、ブラウザーがそれを実行するのをキャンセルし (ダウンロードプロンプトを表示するなど)、Edit1 ボックスに URL を配置して、行動する。さらに詳しく調べてみると、問題のヘッダーを見て、ダウンロードする必要のあるファイルを Web サイトが送信するつもりかどうかを判断できると思います。URL 自体には「CSVファイル」(置くhttp://financials.morningstar.com/ajax/ReportProcess4CSV.html?t=AAPL®ion=usa&culture=us_EN&reportType=is&period=12&dataType=A&order=asc&columnYear=5&rounding=3&view=raw&productCode=USA&r=809199&denominatorView=raw&number=3を Web ブラウザーに問題の CSV ファイルをダウンロードします)。

うまくいけば、それはあなたにとって良いスタートです。

于 2012-11-14T21:20:04.427 に答える