为了账号安全,请及时绑定邮箱和手机立即绑定

将任何 UTF8 编码的 HTML 源代码存储在 MariaDB/MySQL UTF-8 表中

将任何 UTF8 编码的 HTML 源代码存储在 MariaDB/MySQL UTF-8 表中

PHP
心有法竹 2022-07-09 09:44:05
我正在使用 PHP 将 HTML5 代码存储在 Maria 数据库中。在将 HMTL5 内容存储在数据库中之前,我使用解码实体$Uncoded_content = mysqli_real_escape_string($database_link, html_entity_decode($HTML5_content,ENT_QUOTES | ENT_HTML5 ,'UTF-8')); 其中 $HTML_content 是 HTML5 源代码,带有实体编码。我很生气,几个月后,存储各种字符(包括“<”、撇号、引号等)没有任何问题,我在 HTML 表格中看到,其中单元格中有一些“<”符号在公式中) 有些文字根本没有显示。检查数据库中存储的内容后,HTML 代码很好,未解码并且包含所有字符。最后,我发现如果我不在“<”符号前后留一个空格,网络浏览器会使一些文本消失。很明显,浏览器将“<”解释为打开标签。这是 HTML5 源代码内容,因为它存储在数据库中。<table cellpadding="2" cellspacing="0" width="570">  <tr>    <td>Zona lumínica</td>    <td>Superficie del cartel</td>    <td>Luminancia máxima (cd/m2)</td>  </tr>  <tr>    <td>E1</td>    <td>n/a</td>    <td>50</td>  </tr>  <tr>    <td>E2</td>    <td>n/a</td>    <td>400</td>  </tr>  <tr>    <td rowspan="3">E3</td>    <td>S      <2m<sup>2</sup>    </td>    <td>800</td>  </tr>  <tr>    <td>2      <S≤10m<sup>2</sup>    </td>    <td>600</td>  </tr>  <tr>    <td>S>10m<sup>2</sup></td>    <td>400</td>  </tr>  <tr>    <td rowspan="4">E4</td>    <td>S      <0,5m<sup>2</sup>    </td>    <td>1.000</td>  </tr>  <tr>    <td>0,5      <S≤2m<sup>2</sup>    </td>    <td>800</td>  </tr>  <tr>    <td>2      <S≤10m<sup>2</sup>    </td>    <td>600</td>  </tr>  <tr>    <td>S>10m<sup>2</sup></td>    <td>400</td>  </tr></table><p><br /><br /></p><table cellpadding="2" cellspacing="0" width="570">  <tr>    <td>Zona lumínica</td>    <td>Superficie del cartel</td>    <td>Luminancia máxima (cd/m2)</td>  </tr>  <tr>    <td>E1</td>    <td>n/a</td>    <td>50</td>  </tr>  <tr>    <td>E2</td>    <td>n/a</td>    <td>400</td>  </tr>  <tr>    <td rowspan="3">E3</td>    <td>S      < 2m<sup>2</sup>    </td>    <td>800</td>  </tr>两个表是相同的,除了第二个表在每个“<”之前和之后都有空格,这些“<”在某些单元格中显示为原始文本 CONTENT。第一个表没有那些空格。当我做一个简单的“回声”echo $HTML5_source_content来自该内容的 PHP(在 HTML5 结构中),显示第一个表并隐藏了一些文本。第二张表完全显示,因为它应该。为了避免这个问题,我尝试了:echo htmlentities($HTML5_source_content, ENT_QUOTES | ENT_HTML5, "UTF-8"); 但在这种情况下,浏览器不会显示已解析的 HTML 源代码,而是显示源代码本身(页面的其余部分显示为 HTML)。我什至尝试使用“htmlspecialchars”,但结果相同,源代码。我忘记了什么?我的错误在哪里?
查看完整描述

3 回答

?
守着一只汪

TA贡献1872条经验 获得超4个赞

如果您想按原样保存来自作者的 HTML 代码并将其作为“工作”HTML 代码输出到页面上,则不要使用任何 HTML 编码/解码功能。将接收到的内容“按原样”保存在数据库中,稍后用 正常“按原样”输出 HTML echo,就像它是没有 HTML 代码的“正常”内容一样。请记住,这是一个巨大的安全问题,因为作者可以使用他们的 HTML 编辑器软件编写他们喜欢的任何 HTML 代码。他们可以添加任何 HTML 代码,包括 javascript 代码。你被警告了!


对于可以替换为各自字符(如&oacute;to ó)的 HTML 实体,使用该get_html_translation_table()函数获取这些字符的映射。HTML_SPECIALCHARS从映射中减去映射,HTML_ENTITIES因为您只需要非 HTML 相关的映射。使用array_diff()方法来做到这一点。使用映射启动一个简单的str_replace()调用,用它们的字符替换所有实体。


$text = '<b>Ram&oacute;n</b>, formula <code>a &lt; b</code>, <a href="link.html">some link</a> content. Some&nbsp;spaced&nbsp;words.';

$mapping = get_html_translation_table(HTML_ENTITIES);

$mapping = array_diff($mapping, get_html_translation_table());


echo $text."\n";

echo str_replace(array_values($mapping), array_keys($mapping), $text);

出于测试目的,这将生成以下输出:


<b>Ram&oacute;n</b>, formula <code>a &lt; b</code>, <a href="link.html">some link</a> content. Some&nbsp;spaced&nbsp;words.

<b>Ramón</b>, formula <code>a &lt; b</code>, <a href="link.html">some link</a> content. Some spaced words.

如您所见,与 HTML 相关的实体保持为实体,而其他实体被其字符替换。在将原始 HTML 代码保存到数据库之前应用此转换。


对于数据库中已经解码的 HTML 内容:你不走运。没有万无一失的方法可以将与 HTML 相关的字符“重新编码”<回它们的&lt;实体,因为您不知道哪个是/是 HTML 代码,哪个是/是“内容”。你可以做出很好的猜测,比如


文本< b应该是&lt; b并且文本<b应该保持原样,因为那是 HTML 代码。


但这仍然只是(好/坏)猜测。


查看完整回答
反对 回复 2022-07-09
?
鸿蒙传说

TA贡献1865条经验 获得超7个赞

这不是奇怪的行为;这是您要求计算机执行的操作。您要求它存储 HTML 文档,然后为了进行搜索工作,您要求它解码HTML 文档中的所有实体,导致(在某些情况下)文档的含义发生变化,并导致(在最坏的情况下)您的文件将失效。

不要将 HTML 存储在数据库中。您应该生成用于呈现的 HTML,而不是用于存储。以语义方式存储您的数据。(MySQL 具有文本搜索功能;HTML 只是让这更难。)

以演示标记格式存储它,并剥离所有上下文信息(通过解码实体)给您留下了无法可靠使用的数据。当您拥有 时&lt;,您现在拥有<,并且在批量解码所有实体之前无法知道哪个是哪个。

你把牛奶放入水中搅拌。你不能把水弄回来。

你需要明白你的方法从根本上是有缺陷的。您应该检查决策过程中的每个步骤,并再次向自己解释。

然后将漂亮的普通字符串存储在您的数据库中,而不是 HTML。

如果由于某种原因这是不可能的,至少停止解码实体。这会使搜索变得更加困难,因为简单的文本搜索是不够的,但实际上您的搜索例程应该是 HTML 感知的,以便获得正确的结果,所以您最好做对。


tl;博士:

很明显,浏览器将“<”解释为打开标签。

因为它是。这就是<在 HTML 中所做的。

很好,&lt;但后来你逃脱了它。


查看完整回答
反对 回复 2022-07-09
?
潇潇雨雨

TA贡献1833条经验 获得超4个赞

这似乎并不容易,但咨询其他想法来解决类似问题,我编写了这个脚本,它解决了我将任何 HTML 内容存储到 MariaDB/MySQL 数据库(UTF-8 表)并检索以显示为 UTF-8 网页而无需问题。在我的例子中,用户从文字处理器粘贴文本,很多时候他们有印刷字符(双引号和单引号),我们用非印刷字符替换它们,让用户也可以搜索它们。


function PREPARE_TO_STORE($HTML_Code)

{

    $V_Matches = Array();

    $Token = '###TOKEN_HTML###';

    // We will replace typographic characters by non typographical ones and will remain "<" as an HTML entity

    $V_Search  = array( "‘", "’", "”", "“", "″", "<");  

    $V_Replace = array( "'", "'", '"', '"', '"', "&lt;");


    preg_match_all("@<[^>]*>@", $HTML_Code, $V_Matches);

    $V_Content = preg_replace("@(<[^>]*>)@", $Token, $HTML_Code); // $V_Content will contain string between HTML tags

    $V_Content = explode($Token, $V_Content); // Splits HTML from content 


    for ($i=0; $i<count($V_Content); $i++) // Decoding all entities

    {

       $V_Content[$i] = html_entity_decode($V_Content[$i], ENT_QUOTES | ENT_HTML5, "UTF-8");

       $V_Content[$i] = str_replace($V_Search, $V_Replace, $V_Content[$i]);

    }

    $V_Content = join($Token, $V_Content); // Join again HTML tags with content        


    for ($i=0; $i<count($V_Matches[0]); $i++)  

        $V_Content = preg_replace("@$Token@", $V_Matches[0][$i], $V_Content, 1);

    return $V_Content;

}


$HTML_to_store_in_db = mysqli_real_escape_string($link,  PREPARE_TO_STORE($anuncio));


// Here your own code to store $HTML_to_store_in_db in your database

要显示我们存储的 HTML 代码,只需执行以下操作:


echo $HTML_data_retrieved_from_DB;

但如果您的网页不是 UTF-8,也许您需要这样做


echo htmlspecialchars($HTML_data_retrieved_from_DB, ENT_QUOTES | ENT_HTML5, "webpage_coding");  // "webpage_coding" is your character coding, in our case, UTF-8

当然,欢迎任何建议、问题或修复


查看完整回答
反对 回复 2022-07-09
  • 3 回答
  • 0 关注
  • 193 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号