如何保持嵌入式浏览器提示在哪里保存下载的文件? [英] How do I keep an embedded browser from prompting where to save a downloaded file?
问题描述
如何在程序中点击下载按钮后下载文件,因此无需知道下载文件的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屋!