在Delphi中使用UTF8生成动态HTML页面

时间:2012-06-28 14:07:34

标签: delphi delphi-xe

我正在使用Delphi字符串(Delphi XE)动态生成HTML。将重音字符编码到我的HTML中的正确方法是什么?

var
 s : string;
 myHTML : string;

(...)
s:= 'programação';
 myHTML:= 
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'+#10+
'<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">'+#10+
(...)
'<title>OmneeK Server - Intraweb</title>'+#10+
'<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />'+#10+
(...)

myHTML:= myHTML + '<font color="red">' + s + '</font>';

(...)

使用上面的代码(来自浏览器):

"programa��o"

我尝试过使用HTMLEncode但结果是一样的。我正在使用ICS组件来处理HTTP请求。

5 个答案:

答案 0 :(得分:4)

您似乎没有以UTF-8编码保存页面

试试这个样本

Var
  Page :  TStrings;
begin
  Page:=TStringList.Create;
  try
    Page.Add('<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en">');
    Page.Add('<meta http-equiv="Content-Type" content="text/html; charset="UTF-8" />');
    Page.Add('<title>Test</title>');
    Page.Add('<p>programação</p>');
    Page.Add('</html>');
    Page.SaveToFile(ChangeFileExt(ParamStr(0),'.html'), TEncoding.UTF8);
  finally
    Page.Free;
  end;
end;

答案 1 :(得分:2)

@Miguel E

我发现了一些有趣的Delphi XE4 / Indy 10(可能也适用于早期版本)。这可能是你问题的根源吗?

如果您在写入TIdHTTPResponseInfo.CharSet之后写入TIdHTTPResponseInfo.ContentType,那么您将失去写给TIdHTTPResponseInfo.CharSet的内容!

换句话说:(给定信息:TIdHTTPResponseInfo)

  Info.ContentType := 'text/html';   // Warning!  Setting this AFTER setting CharSet changes CharSet back to ISO8859-1.
  Info.CharSet := 'UTF-8';           // So we MUST set CharSet last!

实际上,除了写入Info.ContentText之外,还有其他事情要做,以便使(例如)中文字符的UTF-8编码有效。实际上,您不需要使用流。如果没有意外撤消CharSet属性,那么写入普通Delphi字符串的任何中文(或其他依赖于Unicode的语言)在分配给TIdHTTPResponseInfo.ContentText时都会起作用。

答案 2 :(得分:1)

请务必使用UTF8 编码保存文件。 例如,使用MyHTML变量作为TStringList

MyHTML.SaveToFile(HTMLFileName, TEncoding.UTF8);

它适用于我的应用程序,只有一个TStringList和这行代码。

答案 3 :(得分:1)

  

我正在生成一个运行时字符串,并将该字符串作为对HTTP Server组件(ICS)的响应返回。是否可以将TEncoding应用于字符串?

是。 Delphi String是XE中的UnicodeString。自D2009以来,Delphi一直支持UTF-8编码的字符串。

您可以做的一件事就是将原始UnicodeString分配给UTF8String变量,然后让RTL将Unicode数据编码为UTF-8,然后您可以发送原始字节UTF8String给客户:

var 
  myHTML: string;  
  myHTMLUtf8: UTF8String; 

myHTML := ...
myHTMLUtf8 := myHTML;
// send myHTMLUtf8 as-is...

另一种选择是将UTF-8数据作为TStream发送。您可以将UTF8String放入TMemoryStream

var 
  myHTML: string;  
  myHTMLUtf8: UTF8String;
  strm: TMemoryStream;

myHTML := ...
myHTMLUtf8 := myHTML;

strm := TMemoryStream.Create;
strm.Write(myHTMLUtf8[1], Length(myHTMLUtf8) * SizeOf(AnsiChar));
strm.Position := 0;
// send strm as-is...
strm.Free;

或者将原始UnicodeString放入TStringStream并应用了TEncoding.UTF8

var 
  myHTML: string;  
  strm: TStringStream;

myHTML := ...

strm := TStringStream.Create(myHTML, TEncoding.UTF8);
// send strm as-is...
strm.Free;

答案 4 :(得分:0)

发布此问题后,我发现HTMLEncode函数存在一些问题(在HTTPApp单元中找到),并且HTMLEscape函数(在HTTPUtil单元中找到)也是如此。文档说不多,但在重试HTMEscape功能后,浏览器显示正确的重音。

我不知道是否有更好的解决方法。