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



我正在开发一个http服务器与Netty。在某些情况下,服务器必须响应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 ?我可以改变吗?是否有人有线索的起源问题,以及如何确保它将工作,无论用户的设置?

谢谢

是否接受编码并不是Firefox的问题。是你的服务器。

当你做base64解码时,你会产生一个包含一些字符的字符串…但你真正产生的是字节,然后你把它们想象成字符。因为Java String是一个保存UTF-16字符串的容器,在实践中你所做的就是取每个字节,把它当作一个16位整数,然后构造由这些代码单元组成的UTF-16"字符串"。

但是当你想把所有这些放到网络上时,你必须把字符串转换成字节,copiedBuffer的参数告诉你怎么做。如果转换为UTF-8,则来自设置了高位的字节的任何字符最终将被编码为两个字节的UTF-8序列。另一方面,如果转换为ISO-8859-1,则转换只是删除每个UTF-16代码单元的高字节(在您的情况下始终是零)。

因此,转换到ISO-8859-1会产生您从base64解码中得到的实际字节数组,而转换到UTF-8会产生....其他一些可能有意义,也可能没有意义的东西,这取决于确切的字节值

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

创建一个新的大端缓冲区,其内容为指定的字符串以指定的字符集编码。

这意味着您的二进制数据被"转换"为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));

最新更新