当 base64 null 后跟 =? 时,HTML5 数据 URI 失败
我正在用 JavaScript 做一些非常邪恶的事情,并且遇到了一个奇怪的问题。
我正在创建填充静态大小的缓冲区的二进制数据。如果内容未填满缓冲区,则剩余部分将用空字符填充。
下一步是转换为 base64。
大小(字节)并不总是 3 的倍数,因此我可能需要在末尾添加填充。缓冲区中的最后一个字节始终为空(实际上,大约有 1 kb 的空值)。
当我在 Firefox 和 Chrome 上将其转换为 base64 时,当我有尾随“=”时,我会收到 ERR_INVALID_URL
,但如果没有尾随“=”,则下载效果很好。
例如:
var url = "data:application/octet-stream;base64,";
window.open(url + "AAAA"); // works
window.open(url + "AAAA="); // doesn't work
window.open(url + "icw="); // works
我的文件可以工作,但不符合规范。
这是否有一个无效的base64原因?更重要的是,这是一个错误还是规范的一部分?
编辑:
我发布了一个答案,给出了 Firefox 和 Chrome 之间的一些奇怪之处。有谁知道标准规定了什么?或者是那些松散的规范之一导致了碎片化?如果可能的话,我想要一些明确的东西。
I'm doing some pretty unholy things with JavaScript, and I've run into a weird problem.
I am creating binary data that fills a buffer of a static size. If the content doesn't fill the buffer, the remainder is filled with null characters.
The next step is to convert to base64.
The size (bytes) isn't always a multiple of 3, so I may need to add padding to the end. The last bytes in the buffer are always null (actually, it's about a kb of nulls).
When I convert this to base64 on Firefox and Chrome, I get an ERR_INVALID_URL
when I have a trailing '=', but it downloads fine when I don't.
For example:
var url = "data:application/octet-stream;base64,";
window.open(url + "AAAA"); // works
window.open(url + "AAAA="); // doesn't work
window.open(url + "icw="); // works
My files work, but they're not up to spec.
Is there a reason why this is invalid base64? More importantly, is this a bug or part of the specification?
Edit:
I've posted an answer that gives some of the oddities between Firefox and Chrome. Does anyone know what the standard specifies? Or is it one of those loose specifications that causes fragmentation? I'd like something definitive if possible.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
填充字符
=
用于填充最多四个代码字符的倍数。由于输入的每三个字节都会映射到输出的四个字节,因此输入字节数不是三的倍数时需要填充(余下一个字节需要==
,余下两个字节需要填充)需要=
)。在您的情况下,
AAAA
已经是有效的代码字,不需要填充。The padding character
=
is used to fill up to a multiple of four code characters. As every three bytes of input are mapped onto four bytes of output, a number of input bytes that is not a multiple of three requires padding (a remainder of one byte requires==
and a remainder of two bytes requires=
).In you case
AAAA
already is a valid code word and doesn’t require padding.为什么您认为在字符串末尾添加“=”字符会起作用?这不是 Base64 中的有效字符。
字符集为大小写字母;数字;以及“+”和“/”。因此,任何其他内容在 Base64 字符串中都是无效的。
编辑 - 对于URL来说,似乎你使用“-”和“_”而不是“+”和“/”(对于字符集中的位置62和63)。
再编辑一些 - 这是一个非常令人困惑的话题,因为存在不同的、看似权威但相互矛盾的信息来源。例如,Mozilla 对数据 URL 方案的描述没有提及使用“文件名友好” " 替代编码。 IETF 数据 URL RFC 也是如此。然而,其他 IETF 文档清楚地讨论并指定了用“-”和“_”替换有问题的(对于文件名)“+”和“/”的变体。
因此,我声明自己无知:-) Gumbo 可能是对的,您收到的抱怨是关于不正确的填充(即,在实际上不需要填充时进行填充)。
Why would you imagine that adding an "=" character to the end of the string would work? That's not a valid character in base64.
The character set is upper- and lower-case letters; the digits; and "+" and "/". Anything else is therefore not valid in a base64 string.
edit — well for URLs it seems that instead of "+" and "/" you use "-" and "_" (for positions 62 and 63 in the character set).
edit some more — this is a very confusing topic due to the existence of different, apparently authoritative but contradictory, sources of information. For example, the Mozilla description of the data URL scheme makes no mention of using the "filename-friendly" alternate encoding. Same goes for the IETF data url RFC. However, other IETF documents clearly discuss and specify the variation with "-" and "_" replacing the problematic (for file names) "+" and "/".
Therefore, I declare myself ignorant :-) Gumbo is probably right, that the complaints you're getting are about incorrect padding (that is, padding when no padding is actually necessary).
不同浏览器注意事项:
datalength % 4 === 1
- 需要一个等于datalength % 4 === 2
- 两个相等是必要的这是我用来测试它的行(我每次用不同的字符串替换 AAAAAA==):
var url = "data:application/octet-stream;base64,AAAAAA= =”; window.open(url);
此外,Firefox 和 Chrome 都使用
+
&/
,而不是-
和_
。来源:
我在 Ubuntu 11.04 上使用 Chrome 11 和 Firefox 4 进行的测试。
编辑:
我需要的代码是 tar JavaScript 实用程序。我的代码按原样工作,但我希望尽可能符合标准,并且我认为我缺少一个字节。没什么大不了的,因为 Linux 中的 tar 可以识别它。
Notes about different browsers:
datalength % 4 === 1
- a single equals is necessarydatalength % 4 === 2
- two equals are necessaryThis is the line I used to test it (I replaced AAAAAA== with a different string each time):
var url = "data:application/octet-stream;base64,AAAAAA=="; window.open(url);
Also, both Firefox and Chrome use
+
&/
, not-
and_
.Source:
My tests on Ubuntu 11.04 with Chrome 11 and Firefox 4.
Edit:
The code I need this for is a tar utility for Javascript. My code works as is, but I'd like to be as standards-compliant as possible, and I'm missing a byte I think. No biggie because tar in Linux recognizes it.