2

我正在用 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, "image/gif"); 在 Chrome 中,一切都很好。但是,Firefox 告诉我它无法显示像素(这对我的应用程序来说非常糟糕),因为像素数据无效。经过多次调查,我终于找到了解决办法,将字符集更改为 Iso-8859-1。

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

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

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

谢谢

4

2 回答 2

1

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

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

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

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

于 2013-04-09T07:22:12.200 回答
0

您调用的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));
于 2013-04-08T20:15:32.867 回答