0

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

我的压缩函数首先使用此函数将 html 转换为字节数组。然后它使用js-deflate 库压缩数组。最后,使用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 解码。然后它使用 RubyZlib标准库来解压缩 html。此Stack Overflow 问题线程中描述了此过程。

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 主页,结果如下:

已处理的 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

一个关键是字符串的编码似乎在ASCII-8BIT经过 Base64 解码后更改为:

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">&#9662;</span>
没有元 Content-Type 的 <span class="profile-triangle">¾</span>
膨胀源:具有元 Content-Type 的膨胀源: <span class="profile-triangle">�&lt;/span>

4

3 回答 3

2

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

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

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

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

于 2012-10-23T14:49:58.503 回答
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 被指定为 is utf-8。如果创建文件,则需要使用 HEAD 中的 HTML 标记手动设置内容类型,正如@alexandernst 所建议的那样。

于 2012-10-23T17:37:24.763 回答
0

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

<meta charset="UTF-8">

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

于 2012-10-24T12:21:15.080 回答