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

在Delphi中用UTF8生成动态HTML页面,delphi,delphi-xe,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+

我正在使用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>';

(...)

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

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

MyHTML.SaveToFile(HTMLFileName, TEncoding.UTF8);

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

看来您没有用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;
Var
页码:t字符串;
开始
页面:=TStringList.Create;
尝试
第页。添加(“”);

添加('在发布这个问题后,我发现HTMLEncode函数(在HTTPApp单元中找到)和HTMLEscape函数(在HTTPUtil单元中找到)存在一些问题同样,文档中没有说太多,但在使用HTMLescape函数重试后,浏览器显示了正确的重读

我不知道是否有更好的方法来解决这个问题

我正在生成一个运行时字符串,并将该字符串作为对HTTP服务器组件(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...
另一个选项是以
TStream
的形式发送UTF-8数据。您可以将
UTF8String
放入
TMemoryStream

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

myHTML := ...
myHTMLUtf8 := myHTML;

strm := TMemoryStream.Create;
strm.WriteBuffer(PAnsiChar(myHTMLUtf8)^, 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;
@米格尔E

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

如果在写入TIdHTTPResponseInfo.CharSet后再写入TIdHTTPResponseInfo.ContentType,则会丢失写入TIdHTTPResponseInfo.CharSet的内容

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


事实上,为了使(比如)中文字符的UTF-8编码工作,您不需要做任何其他事情(除了写入Info.ContentText)。您实际上不需要使用流。任何中文(或其他依赖Unicode的语言)如果字符集属性没有意外撤消,则写入普通Delphi字符串将在分配给TIdHTTPResponseInfo.ContentText时起作用。

谢谢,但我不会将动态页面保存到文件中。我正在生成运行时字符串,并将该字符串作为对HTTP服务器组件(ICS)的响应返回。是否可以将TEncoding应用到字符串中?是否尝试将响应的内容类型设置为
text/html charset=UTF-8
?还可以将这些详细信息和代码(关于
…将字符串作为响应返回到HTTP服务器组件
)添加到您的问题中,以获得更好的答案。我是(正如您在上面看到的)。我发现在HTTPUtil下有一个名为HTMLEscape的函数,这个函数可以满足我的需要。这个函数应该和HTMLEncode(在HTTPApp单元中)一样工作但是它没有。我检查了一些评论,似乎Embarcadero把它留下了。官方文档对此一无所知。我不知道这是否是最有效的解决方案,但浏览器现在显示了正确的重读。当我说
时。尝试将内容类型text/html charset=UTF-8
添加到响应中发送到发送数据的组件(作为HTTP头的一部分),无论如何,如果
HTMLEscape
函数修复了您的问题,请将其作为答案发布。谢谢,但我这样做没有生成文件。是否可以将此编码包含到字符串中?谢谢。我相信这是解决问题的最干净的方法。关于ICS HTTPServer组件,它们也提供了一个应答流,因此stream方法将起作用。除非使用UTF8ToAnsiStr转换,否则UTF8String不会起作用,然后性能将受到双重转换的影响。
UTF8ToAnsiStr()
只有在
HTTPServer
让您为输出分配
AnsiString
时才有意义。事实上,在XE中,
System.Utf8ToAnsi()
UTF8String
解码回
UnicodeString
,因此根本不值得使用
UTF8String
,除非您使用
TStream
appraoch,或手动发送
UTF8String
字节。
TStringStream.Create(myHTML,TEncoding.UTF8)在Delphi 10 Seattle中,
没有为我生成BOM。我做错了什么?@Paul你没有做错任何事。它不应该生成BOM。而且你也不应该在HTML中包含BOM。HTML中的
元素和HTTP响应中的
内容类型
头告诉你呃,HTML是用UTF-8编码的。@Paul如果你需要一个BOM表(仅供参考,你不需要),那么你必须使用
TMemoryStream
,并在编写HTML之前手动将BOM表写入流中。阅读所有答案,奇怪的是没有人指出实际问题:UTF8(文件,但也有HTTP响应)数据应该以字节顺序标记开头。对于UTF8,这是
\$EF \$BB \$BF
,但是使用
TStringStream.Create(myHTML,TEncoding.UTF8);
可以为您实现这一点。@Stijn Sanders:
TStringStream.Create(myHTML,TEncoding.UTF8);
在Delphi10西雅图没有为我生成BOM。我做错了什么?。显然TStreamStream构造函数上的编码参数仅用于获取初始数据参数字符串的“字节”。请注意
var 
  myHTML: string;  
  strm: TStringStream;

myHTML := ...

strm := TStringStream.Create(myHTML, TEncoding.UTF8);
// send strm as-is...
strm.Free;
  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!