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

我正在使用 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”,但结果相同,源代码。


我忘记了什么?我的错误在哪里?


心有法竹
浏览 194回答 3
3回答

守着一只汪

如果您想按原样保存来自作者的 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 代码。但这仍然只是(好/坏)猜测。

鸿蒙传说

这不是奇怪的行为;这是您要求计算机执行的操作。您要求它存储 HTML 文档,然后为了进行搜索工作,您要求它解码HTML 文档中的所有实体,导致(在某些情况下)文档的含义发生变化,并导致(在最坏的情况下)您的文件将失效。不要将 HTML 存储在数据库中。您应该生成用于呈现的 HTML,而不是用于存储。以语义方式存储您的数据。(MySQL 具有文本搜索功能;HTML 只是让这更难。)以演示标记格式存储它,并剥离所有上下文信息(通过解码实体)给您留下了无法可靠使用的数据。当您拥有 时&lt;,您现在拥有<,并且在批量解码所有实体之前无法知道哪个是哪个。你把牛奶放入水中搅拌。你不能把水弄回来。你需要明白你的方法从根本上是有缺陷的。您应该检查决策过程中的每个步骤,并再次向自己解释。然后将漂亮的普通字符串存储在您的数据库中,而不是 HTML。如果由于某种原因这是不可能的,至少停止解码实体。这会使搜索变得更加困难,因为简单的文本搜索是不够的,但实际上您的搜索例程应该是 HTML 感知的,以便获得正确的结果,所以您最好做对。tl;博士:很明显,浏览器将“<”解释为打开标签。因为它是。这就是<在 HTML 中所做的。很好,&lt;但后来你逃脱了它。

潇潇雨雨

这似乎并不容易,但咨询其他想法来解决类似问题,我编写了这个脚本,它解决了我将任何 HTML 内容存储到 MariaDB/MySQL 数据库(UTF-8 表)并检索以显示为 UTF-8 网页而无需问题。在我的例子中,用户从文字处理器粘贴文本,很多时候他们有印刷字符(双引号和单引号),我们用非印刷字符替换它们,让用户也可以搜索它们。function PREPARE_TO_STORE($HTML_Code){&nbsp; &nbsp; $V_Matches = Array();&nbsp; &nbsp; $Token = '###TOKEN_HTML###';&nbsp; &nbsp; // We will replace typographic characters by non typographical ones and will remain "<" as an HTML entity&nbsp; &nbsp; $V_Search&nbsp; = array( "‘", "’", "”", "“", "″", "<");&nbsp;&nbsp;&nbsp; &nbsp; $V_Replace = array( "'", "'", '"', '"', '"', "&lt;");&nbsp; &nbsp; preg_match_all("@<[^>]*>@", $HTML_Code, $V_Matches);&nbsp; &nbsp; $V_Content = preg_replace("@(<[^>]*>)@", $Token, $HTML_Code); // $V_Content will contain string between HTML tags&nbsp; &nbsp; $V_Content = explode($Token, $V_Content); // Splits HTML from content&nbsp;&nbsp; &nbsp; for ($i=0; $i<count($V_Content); $i++) // Decoding all entities&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp;$V_Content[$i] = html_entity_decode($V_Content[$i], ENT_QUOTES | ENT_HTML5, "UTF-8");&nbsp; &nbsp; &nbsp; &nbsp;$V_Content[$i] = str_replace($V_Search, $V_Replace, $V_Content[$i]);&nbsp; &nbsp; }&nbsp; &nbsp; $V_Content = join($Token, $V_Content); // Join again HTML tags with content&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; for ($i=0; $i<count($V_Matches[0]); $i++)&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; $V_Content = preg_replace("@$Token@", $V_Matches[0][$i], $V_Content, 1);&nbsp; &nbsp; return $V_Content;}$HTML_to_store_in_db = mysqli_real_escape_string($link,&nbsp; 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");&nbsp; // "webpage_coding" is your character coding, in our case, UTF-8当然,欢迎任何建议、问题或修复
打开App,查看更多内容
随时随地看视频慕课网APP