【问题标题】:How to show relative-path images in TWebBrowser?如何在 TWebBrowser 中显示相对路径图像?
【发布时间】:2017-02-02 13:08:52
【问题描述】:

我在 DesignMode (Doc.DesignMode := 'On') 中使用 TWebBrowser 来编写 HTML 文档。 TWebBrowser 中没有加载文档(磁盘上的 HTML 文件)。我直接在 TWebBrowser 中从零开始创建文档。 html 代码将从 TWebBrowser 中提取并保存为 c:/MyProjects/SomeHtmlName.html。

问题是如果我插入的图片有相对路径,它就不会显示它们。

更准确地说,如果我将此代码粘贴到 WebBrowser 中,它将立即显示图像:

<IMG src="file:///c:/MyProjects/resources/R.PNG">

但是,如果我输入:

<IMG border=0 src="resources\R.PNG">
<IMG border=0 src="resources/R.PNG">   <---- preferred so it will work on Linux

它将显示一个图像占位符而不是实际图像。

我需要相对路径,因此如果我更改根路径或将其上传到 FTP 上,网站仍然可以工作。


procedure TForm1.Button1Click(Sender: TObject);
begin
  LoadDummyPage;
  SetHtmlCode('<img src="resources/test_img.PNG">');
  Memo1.Text:= GetHtmlCode;
end;



function TForm1.LoadDummyPage: Boolean;
const FileName: string= 'c:\MyProject\_ONLINE WEB SITE\dummy.html';
begin
  if not Assigned(wbBrowser.Document)
  then wbBrowser.Navigate('about:blank');

  Result := FileExists(FileName);
  if Result
  then wbBrowser.Navigate('file://' + FileName)
  else Caption:= 'file not found';
end;



procedure TForm1.SetHtmlCode(const HTMLCode: string);
var
  Doc: Variant;
begin
  if not Assigned(wbBrowser.Document)
  then wbBrowser.Navigate('about:blank');

  Doc := wbBrowser.Document;
  Doc.Write(HTMLCode);
  Doc.Close;
  Doc.DesignMode := 'On';

  WHILE wbBrowser.ReadyState < READYSTATE_INTERACTIVE
   DO Application.ProcessMessages;

  Doc.body.style.fontFamily := 'Arial';
  Doc.Close;
end;


function TForm1.GetHtmlCode: string;             { Get the HTML code from the browser }
var
  Doc: IHTMLDocument2;
  BodyElement: IHTMLElement;
begin
  if Assigned(wbBrowser.Document) and (wbBrowser.Document.QueryInterface(IHTMLDocument2, Doc) = S_OK) then
  begin
    BodyElement := Doc.body;
    if Assigned(BodyElement) then
      Result := BodyElement.innerHTML;
  end;

  if Result > ''
  then Result := StringReplace(Result, '="about:', '="', [rfReplaceAll, rfIgnoreCase]);  { Fix the 'How stop TWebBrowser from adding 'file:///' in front of my links' bug }
end;

【问题讨论】:

  • 如果可执行文件的当前工作目录是c:/MyProjects/,是否有效?
  • 我可以使用的“hack”是对 HTML 进行后处理并删除“file:///c:/MyProjects/”
  • @mjn42 - 不。可能是因为图像位于“资源”文件夹中?另外,我认为 TWebBrowser 的“根”文件夹是 Internet Explorer 的默认根文件夹(不管它是什么),而不是应用程序的文件夹。
  • @DarkPresidentOfAmerica,你错了。您需要预加载一个 HTML“模板”字符串/流,包括设置所需路径(带有斜杠)的 BASE 标记,例如"file:///c:/MyProjects/"。并切换到编辑模式,您的图像 src 应该是相对的,例如"resources/R.PNG"。您最终提取的 HTML 后编辑应该是 body.innerHTML。用没有 BASE 标记的有效 HTML/Body 包装它并保存到磁盘。

标签: html delphi twebbrowser


【解决方案1】:

您需要预先加载一个有效的 HTML“模板”字符串/流,包括您设置所需路径的 BASE 标记(带有尾部斜杠),例如"file:///c:/MyProjects/"

然后切换到编辑模式,您的图像 SRC 应该是相对的,例如"resources/R.PNG"。您最终提取的 HTML 后编辑应该是 body.innerHTMLbody.outerHTML(无论您需要什么)。您甚至可以获取整个文档来源(google it)。

使用有效的 HTML/Body 包装提取的源代码,不带 BASE 标记,并保存到磁盘 c:\MyProjects

但是为 IMG SRC 生成的代码是完整路径!

对此你无能为力。这就是 DOM 表示 HTML 的方式——不需要 HTML 源代码。这种行为并不一致。并且还取决于 如何 插入图像(我不使用 execCommand 并且有自己的对话框并插入自己的 html 代码)。您需要手动将提取的源 "file:///c:/MyProjects/" 替换为空字符串。至少,我是这样做的。

编辑:您不需要 Navigate() 到外部文件。您可以通过document.write(HTML) 编写“模板”/“空”HTML。

试试这个:

const
  HTML_TEMPLATE = '<html><head><base href="file:///%s"></head><body style="font-family:Arial">%s</body></html>';

procedure TForm1.LoadHTML(HTMLCode: string);
var
  Doc: Variant;
  HTML, Path: string;
begin
  Path := 'D:\Temp\';
  HTML := Format(HTML_TEMPLATE, [Path, HTMLCode]);
  WebBrowser1.Navigate('about:blank');
  Doc := WebBrowser1.Document;
  Doc.Write(HTML);
  Doc.Close;
  Doc.DesignMode := 'On';
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  LoadHTML('<b>Hello</b><img SRC="resources/1.png">');
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  Doc: IHTMLDocument2;
begin
  Doc := WebBrowser1.Document as IHTMLDocument2;
  if Assigned(Doc) then
  begin
    ShowMessage(Doc.body.innerHTML); 
  end;
end;

我的输出是:&lt;B&gt;Hello&lt;/B&gt;&lt;IMG src="resources/1.png"&gt;。在某些情况下,src 可能包含完整路径。我不能 100% 确定这种情况何时发生。但是您需要准备好通过手动替换路径来处理这种情况。没有关于这方面的决定性文件,所以无论如何我都会处理这个问题。

【讨论】:

  • “您需要手动替换...”-但这就是我已经在做的事情(请参阅我在问题下的评论):) 我提供了完整的图像路径,然后'发布处理' HTML 代码从完整转换为相对。而这一切都无需使用复杂的“BASE”。我认为这是一个“黑客”,并希望我可以让 TWeBBrowser 真正使用相对路径:)
  • @DarkPresidentOfAmerica,“希望我可以让 TWeBBrowser 真正使用相对路径”。但是当您使用 BASE 时它确实! :) innerHTML 表示 DOM 实际如何解析源代码。我知道这个替代品是“hacky”,但AFAIK你无能为力。
  • 然后,为了解决这个问题,我将简单地使用完整路径并后处理 HTML 代码以转换为相对路径。
  • 您所说的是否有意义取决于您的使用情况。但是,如果您需要重用输出的 html,您还需要对其进行预处理,这在没有 baae 标签的情况下有点痛苦。
  • 是的。这实际上是相当痛苦的......你需要从 SRC 中提取所有路径,你需要解码 URL,将其转换为 DOS 文件名,使其相对,将其转换回 Linux 路径,然后重新编码。但我做到了:)
【解决方案2】:

我建议使用小型嵌入式 Web 服务器,例如 Internet Direct (Indy) TIdHttpServer,它能够以标准方式处理所有 HTTP 请求。这消除了所有潜在的文件系统问题。

【讨论】:

  • 感谢您的建议,但这个 hack 比我的更极端 :) 想想在计算机上安装 Web 服务器的含义。大多数防病毒程序都会对此发表评论:)
  • 然后才绑定到本地主机(127.0.0.1)。许多进程打开本地端口,AV 不会抱怨。他们可能会抱怨端口扫描。
猜你喜欢
  • 2011-05-20
  • 1970-01-01
  • 1970-01-01
  • 2015-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-04
  • 2014-02-15
相关资源
最近更新 更多