Base64解码Typescript中的嵌入式PDF

问题描述

在XML文件中,我们有一个表示PDF文件的base64编码的字符串,其中包含一些表表示形式,即类似于this example。在解码该PDF文档(即such as this)的base64字符串时,我们最终得到一个大小为66 kB的PDF文档,可以在任何PDF查看器中正确打开该文件

在尝试使用TypeScript中的Buffer(在VSCode扩展名之内),即使用以下函数解码相同的base64编码的字符串时:

function decodeBase64(base64String: string): string {
    const buf: Buffer = Buffer.from(base64String,"base64");
    return buf.toString();
}

// the base64 encoded string is usually extracted from an XML file directly
// for testing purposes we load that base64 encoded string from a local file
const base64Enc: string = fs.readFileSync(".../base64Enc.txt","ascii");
const base64Decoded: string = decodeBase64(base64Enc);

fs.writeFileSync(".../table.pdf",base64Decoded);

我们最终得到了109 kB的PDF,并且该文档无法使用PDF查看器打开。

对于简单的PDF(例如this one),以base64编码的字符串表示形式(例如this),上面的代码有效,并且可以在任何PDF查看器中读取PDF。

我还尝试使用以下方法直接读取PDF文件的本地存储的base64编码表示形式

const buffer: string | Buffer = fs.readFileSync(".../base64Enc.txt","base64");

尽管也不能产生有用的东西。

由于atob(...)不存在(用this suggestionatob替换为Buffer),即使对suggestions进行了小幅修改,其结果仍类似于这个:

const buffer: string = fs.readFileSync(".../base64Enc.txt","ascii");

// atob(...) is not present,other answers suggest to use Buffer for conversion
const binary: string = Buffer.from(buffer,'base64').toString();
const arrayBuffer: ArrayBuffer = new ArrayBuffer(binary.length);
const uintArray: Uint8Array = new Uint8Array(arrayBuffer);

for (let i: number = 0; i < binary.length; i++) {
    uintArray[i] = binary.charCodeAt(i);
}
const decoded: string = Buffer.from(uintArray.buffer).toString();

fs.writeFileSync(".../table.pdf",decoded);

我并没有以可读的PDF结尾。经过“解码”的table.pdf示例的大小为109 kB。

在这里做错了什么?与Notepad ++提供的功能类似,如何解码诸如table.pdf示例之类的PDF以获取可读的PDF文档?

解决方法

如果您使用Uint8Array构造函数从Buffer获得了Uint8Array,就从How to get an array from ArrayBuffer?的答案中大量借用:

const buffer: string = fs.readFileSync(".../base64Enc.txt","ascii");
const uintArray: Uint8Array = new Uint8Array(Buffer.from(buffer,'base64'));
fs.writeFileSync(".../table.pdf",uintArray);

Uint8Array直接写入文件可确保不会因字符串之间的编码更改而损坏。

请注意:Uint8Array指向与Buffer相同的内部字节数组。在这种情况下,这并不重要,因为此代码未在构造函数之外引用Buffer,但是如果有人决定为Buffer.from(buffer,'base64')的输出创建一个新变量。