我正在尝试用 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 主页,结果如下:
你可以看到有一些问题。有些字符没有正确显示,最明显的是标题中我名字旁边的向下箭头
以及最近标签列表中的乘号
如何修复我的代码以便正确处理页面的这些部分?
我试图强制对膨胀的 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">▾</span>
没有元 Content-Type 的 <span class="profile-triangle">¾</span>
膨胀源:具有元 Content-Type 的膨胀源: <span class="profile-triangle">�</span>