TChromium:如何将特定图像保存到文件?

TChromium : how to save a specific image to file?

我正在使用 TChromium,我需要导航到特定页面并将该页面的特定图像保存到文件中。

我知道如何导航和提取 HTML 源以获取图像的地址,但我不知道如何将图像保存到我的本地文件系统。

我如何使用一些 TChromium 方法来做到这一点?

我不想使用其他组件(例如 TIdHTTP)来执行此操作,因为该站点需要登录并且图像依赖于活动会话。

提前致谢!

来自 CEF 论坛:

"CEF does not currently support the extraction of cached resources. You can identify the request that originally returned the content by overriding CefRequestHandler::OnBeforeResourceLoad() and then execute the request yourself using CefWebURLRequest the retrieve and save the contents."

另一种方法是按照此处的要求添加上下文菜单 - TChromium how to add "Save Picture" item in Context Menu? 以及 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.

另一种方法是识别页面中的所有图像(查看How can I use Javascript to get a list of all picture URLs available on a site?)并使用CefBrowserHost.StartDownload下载图像link。

添加到 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;