我正在使用最新版本的puppeteer来生成附加的PDF。当我在Adobe Acrobat中打开它并尝试复制并粘贴文本时,它会变为
这是一个测试字符串。
到
Ţħįşįşǻţěşţşţřįňģ。
以下是我生成PDF的代码。
const puppeteer = require('puppeteer');
const argv = require('minimist')(process.argv.slice(2));
const fileName = argv.fileName || "page";
const timeout = 90;
(async () => {
var pageUrl = "my-url-here"
const browser = await puppeteer.launch();
const page = await browser.newPage();
function onTimeout() {
console.log("Timed out waiting for data after " + timeout + " seconds.");
process.exit();
}
console.log("Opening " + pageUrl);
await page.goto(pageUrl, {waitUntil: 'networkidle2'});
console.log("Waiting for page to load...");
console.log("Waiting for data to load...");
await page.waitForSelector('#print-report-loaded', {timeout:timeout*1000}).catch(onTimeout);
var fileFullName = fileName + ".pdf";
console.log("Saving PDF as " + fileFullName);
await page.pdf({path: fileFullName});
console.log("PDF saved successfully as " + fileFullName);
await browser.close();
})();
Here is link to the generated PDF
任何想法如何解决将不胜感激!
答案 0 :(得分:1)
Acrobat不会更改文本,它只会复制为这些字体存储的Unicode字符。 '字符'你看到的是Type 3的大纲,他们的形式是"常规"字符,但它们相关的Unicode代码点确实是那些重音字符。
从Acrobat Reader和官方PDF规范的角度来看,一切都是"按设计工作"。
让我们来看看你的PDF。
为了让事情变得不必要,人们会认为这只需要一种字体,但是你的工具生成了两个字体:F0
,它将字符代码映射到以下Unicode代码
<(01)> <( )>
<(0D)> <(.)>
<(26)> <(Ț)>
<(32)> <(ǻ)>
<(35)> <(ě)>
<(37)> <(ģ)>
<(38)> <(ħ)>
<(39)> <(į)>
<(3E)> <(ň)>
<(42)> <(ț)>
和F1
映射到
<(15)> <(ř)>
<(16)> <(ș)>
字符代码以字符串形式写出,一次一个字符(中间有几个命令;这里省略,因为不相关):
<26><38><39>{16}<01><39>{16}<01><32><01><42><35>{16}<42><01>{16}<42>{15}<39><3E><37><0D>
我指出<..>
内配对的十六进制代码来自字体F0
而{..}
来自F1
。现在,如果使用Unicode字符逐个替换字符索引,则确实会获得Unicode字符串
Țħįș įș ǻ țěșț șțřįňģ.
&#34;字体&#34;这里使用的是Type 3 PostScript字体,完全嵌入PDF中。例如,字体#0定义为
8 0 obj @ 1059 % "F0"
<<
/Type /Font
/Subtype /Type3
/CIDToGIDMap /Identity
/CharProcs
<<
/g0 11 0 R % -> stream
/g1 12 0 R % -> stream
/g26 14 0 R % -> stream
/g32 15 0 R % -> stream
/g35 16 0 R % -> stream
/g37 17 0 R % -> stream
/g38 18 0 R % -> stream
/g39 19 0 R % -> stream
/g3E 20 0 R % -> stream
/g42 21 0 R % -> stream
/gD 13 0 R % -> stream
>>
/Encoding
<<
/Type /Encoding
/Differences [ 0 /g0 /g1 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /gD /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0
/g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g26 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0 /g0
/g0 /g32 /g0 /g0 /g35 /g0 /g37 /g38 /g39 /g0 /g0 /g0 /g0 /g3E /g0 /g0 /g0 /g42 ]
>>
/FirstChar 0
/FontBBox [ -1 202 598 -801 ]
/FontDescriptor 10 0 R % -> FontDescriptor (Font)
/FontMatrix [ 0.082254 0 0 -0.082254 0 0 ]
/LastChar 66
/ToUnicode 9 0 R % -> stream
/Widths [ 500 300 0 0 0 0 0 0 0 0 0 0 0 244 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 641 0 0 0 0 0 0 0 0 0 0 0 579 0
0 592 0 664 616 263 0 0 0 0 616 0 0 0 404 ]
>>
endobj
除了编码数组之外,其中大部分都不重要,它告诉字符索引与什么字形名称以及CharProcs
数组相关联,它将编码数组中的名称与实际绘图指令相关联。这是来自&#34;字体名称加字符索引&#34;的路线。在字符串中显示&#34;编码&#34;中的字符索引,然后使用ToUnicode
数组查找每个字符的实际(报告的)Unicode值。< / p>
每个字符本身的绘图说明(对每个/gX
流的引用)是move
,line
和fill
指令的常规系列 - 再次,没有虽然其他PDF引擎更常包含原始字体,而不仅仅是文字绘图说明。
但是ToUnicode
表弄乱了复制的东西。而不是说明字符16#26
映射到Unicode U + 0054&Latin Capital T&#39;&#34;,它指向&#34; U + 021A Latin Capital T,逗号低于& #34; - 并且没有明显的原因!它肯定不是随机翻译,但我找不到任何合理的解释,为什么人们会故意编码纯文本......除非有人在那里咧着嘴笑内容和思考,&#34;是的,这是我的想法&#34; - 在这种情况下,它将是故意混淆。
Github上的Puppeteer代码似乎并不处理PDF本身,因此必须由Chromium处理,Chromium内部使用Skia PDF引擎(据报道,但由PDF二进制标题证实,其中包含#34; D3 EB E9 E1&#34; - &#34; Skia&#34;,当最高位被清零时)。它已被报告为一个错误as early as 2012,但有2017年的报告,这似乎表明这不是一个迫切需要解决的问题。