压缩和解压缩Stack Overflow主页HTML

时间:2012-10-23 14:48:03

标签: javascript ruby encoding character-encoding compression

我正在尝试使用JavaScript压缩HTML并使用Ruby解压缩它。但是有些carachters没有正确处理,我正在寻找解决这个问题的方法。

我的压缩函数首先使用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类,第一个base64解码压缩的html。然后它使用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主页,结果如下:

processed Stack Overflow homepage

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

down arrow

和最近的标签列表中的乘法符号

recent tags list

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

我试图强制将膨胀的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

修改以显示向充气的html添加Content-Type元标记的效果

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

question mark box

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

实际SO来源: <span class="profile-triangle">&#9662;</span>
没有元内容类型的充气来源: <span class="profile-triangle">¾</span>
带有元内容类型的充气来源: <span class="profile-triangle">�</span>

3 个答案:

答案 0 :(得分:2)

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

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

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

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

答案 1 :(得分: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所示。

答案 2 :(得分:0)

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

<meta charset="UTF-8">

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