【问题标题】:Compressing and decompressing the Stack Overflow homepage HTML压缩和解压 Stack Overflow 主页 HTML
【发布时间】:2012-10-23 14:48:02
【问题描述】:

我正在尝试使用 JavaScript 压缩 HTML 并使用 Ruby 解压缩它。然而,一些 carachter 没有被正确处理,我正在寻找一种方法来解决这个问题。

我的压缩函数首先使用this function 将html 转换为字节数组。然后它使用js-deflate library 压缩数组。最后,其输出使用window.btoa() 进行base64 编码。

var compress = function(htmlString) {
  var compressed, originalBytes;

  originalBytes = Utils.stringToByteArray(htmlString);
  compressed = RawDeflate.deflate(originalBytes.join(''));
  return window.btoa(compressed);
};

在 Ruby 方面,我有一个 Decompression 类,它首先对压缩的 html 进行 base64 解码。然后它使用 Ruby Zlib 标准库来解压缩 html。这个过程在this Stack Overflow question thread中有描述。

require "base64"
require "zlib"

class Decompression
  def self.decompress(string)
    decoded = Base64.decode64(string)
    inflate(decoded)
  end

private

  def self.inflate(string)
    zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
    buf = zstream.inflate(string)
    zstream.finish
    zstream.close
    buf
  end
end

我正在使用这个类来膨胀压缩的 html,它被发送到本地服务器,并将其写入文件。

decompressed_content = Decompression.decompress(params["compressed_content"])
File.write('decompressed.html', decompressed_content)

然后我在浏览器中打开文件,看看它是否正确。

在大多数情况下,这工作正常。我可以处理 Stack Overflow 主页,结果如下:

你可以看到有一些问题。有些字符没有正确显示,最明显的是标题中我名字旁边的向下箭头

以及最近标签列表中的乘号

如何修复我的代码,以便正确处理页面的这些部分?

我试图将膨胀的 html 的编码强制为UTF-8,但它并没有改变任何东西。

  def self.decompress(string)
    decoded = Base64.decode64(string)
    # Forcing the encoding of the output doesn't do anything.
    inflate(decoded).force_encoding('UTF-8')
  end

  def self.decompress(string)
    decoded = Base64.decode64(string)
    # Either does forcing the encoding of the inflate input.
    inflate(decoded.force_encoding('UTF-8'))
  end

一个关键是字符串的编码在经过Base64解码后似乎变成了ASCII-8BIT

def self.decompress(string)
  p "Before decode: #{string.encoding}"
  decoded = Base64.decode64(string)
  p "After decode: #{decoded.encoding}"
  inflated = inflate(decoded)
  p "After inflate: #{inflated.encoding}"
  inflated
end

# Before decode: UTF-8
# After decode: ASCII-8BIT
# After inflate: ASCII-8BIT

编辑

有人首先询问我用来获取 html 的方法。我只是用 jQuery 把它从页面上拉下来:

$('html')[0].outerHTML

编辑以显示将Content-Type 元标记添加到膨胀的html 的效果

我将<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 添加到膨胀的html 中。我现在得到这样的问号框(顺便说一下 Chrome 浏览器):

.

如果我检查我的膨胀 html 的来源并将其与实际 Stack Overflow html 的来源进行比较,我可以看到我名字旁边的倒三角形使用了不同的字符。

实际 SO 来源:<span class="profile-triangle">▾</span>
没有元内容类型的夸大来源:<span class="profile-triangle">¾</span>
具有元内容的夸大来源 -类型: <span class="profile-triangle">�</span>

【问题讨论】:

  • 您能否先向我们展示一下您是如何获得 HTML 的?
  • 我编辑了帖子的底部以显示这一点。

标签: javascript ruby encoding character-encoding compression


【解决方案1】:

尝试将 UTF8 编码添加到您获得的 HTML 中。喜欢在

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" charset="UTF-8" />

我建议这样做是因为我实际上无法在源代码中看到它(同一页面上的 ctrl+u)。

编辑:原来你错过了字符集!

【讨论】:

  • 但是我的解压功能怎么知道呢?它在输入中所能看到的只是一个压缩字符串。它不知道字符串是否包含元内容类型标记。它甚至不知道字符串中包含 html。
  • 啊..当然。不幸的是,它似乎无法解决问题。我用一些结果编辑了这个问题。
  • 你真的很亲密,但事实证明我实际上需要添加一个 &lt;meta charset="UTF-8"&gt; 而不是 http-equiv 标签。
  • 呃,真的很接近。 :)
  • 完成 :p 事实上,你也可以编写 http-equiv 和内容值!
【解决方案2】:

通常,HTML 的内容类型由 HTTP 标头和 HTML 代码本身决定。 如果只发送 HTML 代码,HTTP 标头信息会丢失。

查看 StackOverflow 发送过来的 HTTP 标头:

Cache-Control:public, max-age=60
Content-Encoding:gzip
Content-Length:33200
Content-Type:text/html; charset=utf-8
Date:Tue, 23 Oct 2012 17:35:02 GMT
Expires:Tue, 23 Oct 2012 17:36:02 GMT
Last-Modified:Tue, 23 Oct 2012 17:35:02 GMT
Vary:*

如您所见,Content-type 被指定为utf-8。如果创建文件,则需要使用 HEAD 中的 HTML 标记手动设置内容类型,正如@alexandernst 建议的那样。

【讨论】:

    【解决方案3】:

    alexandernst 是在正确的轨道上,但我实际上需要添加到 HTML 输出的是元字符集标记:

    <meta charset="UTF-8">
    

    一旦我把它放到 Stack Overflow 主页的 HTML 输出中,它看起来就完美了。

    【讨论】:

      猜你喜欢
      • 2019-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-09
      相关资源
      最近更新 更多