解码由 Java 中的 Base64 和 RFC2047 编码的字符串(来自 header)

Decoding String (from header) encoded by Base64 and RFC2047 in Java

我正在开发一个函数来解码在 Java.

中以 Base64 和 RFC2047 编码的字符串(来自 header)

鉴于此 header:

SGVhZGVyOiBoZWFkZXJ2YWx1ZQ0KQmFkOiBOYW1lOiBiYWRuYW1ldmFsdWUNClVuaWNvZGU6ID0/VVRGLTg/Qj81YmV4NXF5eTU2dUw2SUNNNTZ1TDVMcTY3N3lNNWJleDVxeXk2WUdVNklDTTZZR1U/PSA9P1VURi04P0I/NUxxNjc3eU01YmV4NW9tQTVMaU41cXl5Nzd5TTVZdS81cGE5NXBhODVMcTY0NENDPz0NCg0K

我的预期输出是:

Header: headervalue Bad: Name: badnamevalue Unicode: 己欲立而立人,己欲達而達人,己所不欲,勿施於人。

我发现并尝试过的唯一相关函数是 Base64.decodeBase64(headers),它在打印出来时产生了这个:

Header: headervalue Bad: Name: badnamevalue Unicode: =?UTF-8?B?5bex5qyy56uL6ICM56uL5Lq677yM5bex5qyy6YGU6ICM6YGU?= =?UTF-8?B?5Lq677yM5bex5omA5LiN5qyy77yM5Yu/5pa95pa85Lq644CC?=

为了解决这个问题,我一直在尝试 MimeUtility.decode() 将 Base64.decodeBase64(headers) 返回的字节数组转换为 InputStream,但结果与上面相同。

InputStream headerStream = new ByteArrayInputStream(Base64.decodeBase64(headers));
InputStream result = MimeUtility.decode(headerStream, "quoted-printable");

一直在互联网上搜索,但尚未找到解决方案,想知道是否有人知道如何从结果字节数组中解码 MIME headers?

感谢任何帮助!这也是我的第一个堆栈溢出 post,如果我遗漏了任何内容,我们深表歉意,但如果我可以提供更多信息,请告诉我!

您那里的 base64 实际上是您粘贴的内容。包括奇怪的 =?UTF-8?B?怪异。

后面的内容又是base64.

您的 base-64 编码数据中有 base64 编码的数据。正如 Xzibit 所说:我在你的 base64 中放了一些 Base64,这样你就可以在你使用 base64 的同时使用 base64。为什么突然觉得自己老了?

换句话说,你得到的 base64 输入是疯狂的人发明的一种疯狂的、效率极低的格式。

我的建议是你告诉他们想出一些不那么疯狂的东西。

否则:

在生成的字符串中搜索正则表达式模式,然后再次对中间的内容应用 base64 解码。

此外,您正在使用一些第三方 base64 解码器,可能是 apache。 Apache 库往往很糟糕。 Base64 被烘焙到 java,没有理由在这里使用更差的库。我已经修好了;此代码段中的 Base64 是 java.util.Base64。它的 API 略有不同。

String sourceB64 = "SGV..."; // that input base64 you have.
byte[] sourceBytes = Base64.decodeBase64(sourceB64);
String source = new String(sourceBytes, StandardCharsets.UTF_8);
Pattern p = Pattern.compile("=\?UTF-8\?B\?(.*?)\?=");
Matcher m = p.matcher(source);
StringBuilder out = new StringBuilder();
int curPos = 0;
while (m.find()) {
  out.append(source.substring(curPos, m.start()));
  curPos = m.end();
  String content = new String(Base64.getDecoder().decode(m.group(1)), StandardCharsets.UTF_8);
  out.append(content);
}
out.append(source.substring(curPos));

System.out.println(out.toString());

如果我 运行 那,我得到:

Header: headervalue
Bad: Name: badnamevalue
Unicode: 己欲立而立人,己欲達而達 人,己所不欲,勿施於人。

这看起来和你想要的一模一样。

该代码的解释:

  • 它首先对输入进行 base64 解码,然后将其转换为字符串。 (您使用 InputStream 的想法是转移注意力。这在这里根本没有帮助。您只想将字节转换为字符串,按照该片段的第 3 行执行。传递字节数组并对这些字节进行编码在,这就是你需要做的。
  • 然后它会在你的 base64 中寻找 =?UTF-8?B?--base64here--?=。 base64 中的 base64。
  • 然后解码器 base64,以相同的方式将其转换为字符串,并替换它。
  • 它只是逐字添加 =?UTF-8?B?...?= 段之外的所有内容。