我正在使用TChromium,我需要导航到特定页面并将此页面的特定图像保存到文件中。
我知道如何导航和提取HTML源代码以获取图像的地址,但我不知道如何将图像保存到我的本地文件系统。
我如何使用一些 TChromium 方法?
我不想使用其他组件(例如 TIdHTTP)来执行此操作,因为站点需要登录并且图像依赖于活动会话。
提前感谢!
来自CEF论坛:
"CEF 目前不支持提取缓存资源。 您可以通过以下方式标识最初返回内容的请求 重写 CefRequestHandler::OnBeforeResourceLoad() 然后执行 使用 CefWebURL 请求自己检索并保存 内容。
另一种方法是按照此处的要求添加上下文菜单 - TChromium 如何在上下文菜单中添加"保存图片"项? 以及 TLama 制作代码片段的地方:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtDlgs, IdHTTP, cefvcl, ceflib;
const
MENU_ID_SAVE_IMAGE_AS = Ord(MENU_ID_USER_FIRST) + 1;
type
TDownloader = class(TThread)
private
FURL: string;
FFileName: string;
protected
procedure Execute; override;
public
constructor Create(const URL, FileName: string); reintroduce;
end;
type
TForm1 = class(TForm)
Button1: TButton;
Chromium1: TChromium;
SavePictureDialog1: TSavePictureDialog;
procedure FormCreate(Sender: TObject);
procedure Chromium1BeforeContextMenu(Sender: TObject; const browser: ICefBrowser;
const frame: ICefFrame; const params: ICefContextMenuParams; const model: ICefMenuModel);
procedure Chromium1ContextMenuCommand(Sender: TObject; const browser: ICefBrowser;
const frame: ICefFrame; const params: ICefContextMenuParams; commandId: Integer;
eventFlags: TCefEventFlags; out Result: Boolean);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TDownloader }
constructor TDownloader.Create(const URL, FileName: string);
begin
inherited Create(False);
FreeOnTerminate := True;
FURL := URL;
FFileName := FileName;
end;
procedure TDownloader.Execute;
var
HTTPClient: TIdHTTP;
FileStream: TFileStream;
begin
try
HTTPClient := TIdHTTP.Create;
try
FileStream := TFileStream.Create(FFileName, fmCreate);
try
HTTPClient.Get(FURL, FileStream);
finally
FileStream.Free;
end;
finally
HTTPClient.Free;
end;
except
// error handling ignored for this example
end;
end;
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
begin
Chromium1.Load('http://www.google.com/');
end;
procedure TForm1.Chromium1BeforeContextMenu(Sender: TObject; const browser: ICefBrowser;
const frame: ICefFrame; const params: ICefContextMenuParams; const model: ICefMenuModel);
begin
if (CM_TYPEFLAG_MEDIA in params.TypeFlags) and (params.MediaType = CM_MEDIATYPE_IMAGE) then
model.AddItem(MENU_ID_SAVE_IMAGE_AS, 'Save image as...');
end;
procedure TForm1.Chromium1ContextMenuCommand(Sender: TObject; const browser: ICefBrowser;
const frame: ICefFrame; const params: ICefContextMenuParams; commandId: Integer;
eventFlags: TCefEventFlags; out Result: Boolean);
var
SaveDialog: TSavePictureDialog;
begin
if (commandId = MENU_ID_SAVE_IMAGE_AS) then
begin
SaveDialog := TSavePictureDialog.Create(nil);
try
// SaveDialog.FileName := <here you can extract file name from params.SourceUrl>;
// SaveDialog.DefaultExt := <here you can extract file ext from params.SourceUrl>;
if SaveDialog.Execute then
TDownloader.Create(params.SourceUrl, SaveDialog.FileName);
finally
SaveDialog.Free;
end;
end;
end;
end.
另一种方法是识别页面中的所有图像(看看如何使用Javascript获取网站上所有可用的图片URL的列表?)并使用CefBrowserHost.StartDownload
下载图像链接。
添加到 Form1:
public
var file_download_finished : boolean;
procedure TForm1.Chromium1BeforeDownload(Sender: TObject;
const browser: ICefBrowser; const downloadItem: ICefDownloadItem;
const suggestedName: ustring; const callback: ICefBeforeDownloadCallback);
begin
callback.Cont('FileName.jpg', false);
end;
procedure TForm1.Chromium1DownloadUpdated(Sender: TObject;
const browser: ICefBrowser; const downloadItem: ICefDownloadItem;
const callback: ICefDownloadItemCallback);
var i : nativeint;
begin
if downloadItem.IsComplete then
file_download_finished := true
else
i := downloadItem.PercentComplete;
end;
procedure TForm1.Button1Click(Sender: TObject);
var M: TMsg;
begin
file_download_finished := false;
Chromium1.Browser.Host.StartDownload('https://www.gravatar.com/avatar/7ffbdc105c382c0070cdd29d073725b5?s=48&d=identicon&r=PG&f=1');
repeat // wait until download is finished
while PeekMessage(M, 0, 0, 0, pm_Remove) do
begin
TranslateMessage(M);
DispatchMessage(M);
end;
until file_download_finished;
end;