由于Netty服务器中的内容字符集设置,Firefox中的像素无效

时间:2013-04-08 20:10:21

标签: http firefox character-encoding netty

我正在使用Netty开发一个http服务器。在某些情况下,服务器必须回答1x1透明像素。所以我在base64中对GIF透明像素进行了硬编码,并使用以下代码返回它:

String pixel_string= new String (Base64.decodeBase64("R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="));
HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
response.setContent(ChannelBuffers.copiedBuffer(pixel_string, CharsetUtil.UTF_8));

编辑:我还设置了内容类型:     response.setHeader(HttpHeaders.Names.CONTENT_TYPE,                 “图像/ GIF”); 在Chrome中,一切都很好。但是,Firefox告诉我它无法显示像素(这对我的应用来说非常糟糕),因为像素数据无效。 经过多次调查,我终于找到了一个解决办法,将字符集改为Iso-8859-1。

response.setContent(ChannelBuffers.copiedBuffer(
            responseBuilder.pixel_string, CharsetUtil.ISO_8859_1));

我不明白它为什么会起作用,这让我觉得在某些情况下我可能会遇到麻烦。我试图更改Firefox首选项(默认使用UTF8),但它没有太大变化。

为什么Firefox接受ISO-8859编码,而不接受UTF-8?我可以更改吗?有人会对问题的根源有所了解,以及如何确保无论用户的设置如何都能正常工作?

由于

2 个答案:

答案 0 :(得分:1)

Firefox不接受编码。这是你的服务器。

当你进行base64解码时,你会产生一个包含一些字符的字符串......但是你真正产生的是 bytes ,然后你会以某种方式将其视为字符。由于Java String是一个容纳UTF-16字符串的容器,实际上你所做的就是获取每个字节,将其视为一个16位整数并构造由这些代码单元组成的UTF-16“字符串”

但是当你想把所有这些都放在网络上时,你必须将字符串转换为字节,而copiedBuffer的参数说明如何做到这一点。如果转换为UTF-8,来自具有高位设置的字节的任何字符将最终被编码为双字节UTF-8序列。另一方面,如果转换为ISO-8859-1,转换只会丢弃每个UTF-16代码单元的高字节(在您的情况下总是为零)。

因此,转换为ISO-8859-1会产生你从base64解码中获得的实际字节数组,而转换为UTF-8会产生....其他可能或可能没有任何意义的其他内容取决于确切的字节值。

答案 1 :(得分:0)

您调用的copiedBuffer构造函数不适合您正在使用的数据类型(二进制)。根据Netty API的JavaDoc,您要调用的是:

  

创建一个新的big-endian缓冲区,其内容是指定的字符串   在指定的字符集中编码。

这意味着您的二进制数据被“转换”为UTF-8(这是毫无意义的)。如果您尝试保存生成的文件并使用十六进制编辑器查看它,您可能会看到它已损坏。

尝试这样的事情(未经测试的代码):

static byte[] pixel_data = Base64.decodeBase64("R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==");
HttpResponse response = ...
response.setHeader(HttpHeaders.Names.CONTENT_TYPE, "image/gif");
response.setContent(ChannelBuffers.copiedBuffer(pixel_data));