在Javascript中从base64数据保存二进制文件

Lex*_*Lex 5 javascript

我正在尝试使用 javascript 下载 xlsx 电子表格。我已经测试过 base64 数据。我这样解码:

var data = atob(validBase64Data);

在那之后,我这样做:

save(name, data, type) {
  const blob = new Blob([data], {type: type});
  let objectURL = window.URL.createObjectURL(blob);
  let anchor = document.createElement('a');

  anchor.href = objectURL;
  anchor.download = name;
  anchor.click();

  URL.revokeObjectURL(objectURL);
}
Run Code Online (Sandbox Code Playgroud)

其中 name 是文件名.xlsx,data 是解码后的数据,type 是 mime 类型的字符串。

excel 文件已下载,但不会以 excel 格式打开。数据以某种方式损坏。

另外:我使用 unix 终端命令测试了相同的数据,以 base64 解码并将 xlsx 直接写入该文件,并生成工作文件。测试是这样完成的:

  1. 我将 base64 数据保存到 test_excel.txt`
  2. 跑命令 base64 -D -i test_excel.txt -o test_excel.xlsx
  3. test_excel.xlsx 被 excel 识别。

我对代码做错了什么?

Pat*_*rts 1

好吧,在有人试图错误地“解释”问题之前,让我们澄清一些事情。

原始文件.xlsx是二进制编码的文件,这意味着数据将包含0x00to整个范围内的字节0xFF

在问题中,假设该字符串已成功编码为有效的 base64 字符串,没有无关字符base64(如使用不带标志的测试成功所示-i),并存储到validBase64Data.

问题是atob(validBase64Data)生成一个解码为 utf-8 的字符串,而不是二进制。0x80正如我之前所说,原始二进制字符串包含范围为的非 ASCII 字节0xFF。在 utf-8 中,这些代码点存储为两个字节而不是一个字节,因此解决方案(如在 JavaScript 中从 base64 字符串创建 Blob中所述)是将 utf-8 字符串中每个字符的代码点转换data为bytes 存储为 a Uint8Array,然后从中构造 a Blob

简单的解决方案可能如下所示,但请参阅在 JavaScript 中从 base64 字符串创建 Blob以获得更高性能的解决方案:

const blob = new Blob([Uint8Array.from(data, c => c.charCodeAt(0))], { type });
//...
Run Code Online (Sandbox Code Playgroud)

这使用TypedArray.from(iterable, mapFn).