【问题标题】:pdfjs can't view PDF when containing non standard characeterspdfjs在包含非标准字符时无法查看PDF
【发布时间】:2021-12-15 09:44:57
【问题描述】:

解决方案:要使 HTML 代码正常工作,请交换“reader.readAsText” @KJ 的回答中解释的“reader.readAsBinaryString”

我正在尝试使用 PDFJS 查看 PDF。我有以下代码适用于我从 PDFJS 网站获得的演示 PDF,但它不适用于我尝试过的其他 PDF。这是有效的演示 PDF 的原始文本:

%PDF-1.7
1 0 obj  % entry point
<</Type/Catalog/Pages 2 0 R>>
endobj
2 0 obj<</Type/Pages/MediaBox[ 0 0 200 200]/Count 1/Kids[3 0 R]>>endobj
3 0 obj<</Type/Page/Parent 2 0 R/Resources<</Font<</F1 4 0 R>>>>/Contents 5 0 R>>endobj
4 0 obj<</Type/Font/Subtype/Type1/BaseFont/Times-Roman>>endobj
5 0 obj  % page content
<</Length 44>> stream
BT 70 50 TD /F1 12 Tf(Hello, world!) Tj ET
endstream endobj
xref trailer <</Size 6/Root 1 0 R>> startxref
%%EOF

这是我成功加载上述 PDF 的 html 代码:

<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.2.228/pdf.js"></script>
<input type="file" id="input"/> </br> <canvas id="can" width=1000 height=1000/>
<script>
    document.getElementById('input').addEventListener('change', function(e){
        var reader = new FileReader()
        reader.onload = function(x){
            window['pdfjs-dist/build/pdf'].getDocument({data:x.target.result}).promise.then(function(pdf){
                pdf.getPage(1).then(function(page){
                    page.render({canvasContext:document.getElementById('can').getContext('2d'),
                        viewport:page.getViewport({scale:1})})
        })})}
        reader.readAsText(e.target.files[0])
    }, false)
</script>

但是,我的其他 PDF 根本无法加载。例如,我生成了一个 1 页的 PDF,在背面仅包含单词“TEST”并下载了它。当我尝试将此 PDF 上传到我的 html 代码时,我在控制台中遇到了这些错误:

Warning: Invalid stream: "FormatError: Bad FCHECK in flate stream: 120, 253"
util.js:306 Warning: Indexing all PDF objects
2util.js:306 Warning: Invalid stream: "FormatError: Bad FCHECK in flate stream: 120, 253"
viewPDF.html:1 Uncaught (in promise) InvalidPDFException {name: "InvalidPDFException", message: "Invalid PDF structure"}
Promise.then (async)
reader.onload @ viewPDF.html:7
load (async)
(anonymous) @ viewPDF.html:6

我怀疑我遇到的问题与不工作的 PDF 包含非标准字符有关。以下是来自背页的 PDF 的前几行:

%PDF-1.5
%���
3 0 obj
<< /Linearized 1 /L 11602 /H [ 678 125 ] /O 7 /E 11072 /N 1 /T 11321 >>
endobj

4 0 obj
<< /Type /XRef /Length 51 /Filter /FlateDecode /DecodeParms << /Columns 4 /Predictor 12 >> /W [ 1 2 1 ] /Index [ 3 14 ] /Info 1 0 R /Root 5 0 R /Size 17 /Prev 11322                 /ID [<8f1689fb6a16051fd66ebeadaa364b8d><4a8030207ba6597007a967ed52a9309d>] >>
stream
x�cbd�g`b`8 $��XF@���*��    ��@�Y�����v�#�.
endstream
endobj

5 0 obj
<< /Pages 14 0 R /Type /Catalog >>
endobj
6 0 obj
<< /Filter /FlateDecode /S 36 /Length 48 >>
stream
x�c```e``Z��
            pe31
                B�����,��v�>aW�

编辑:

可以在 Firefox、Chromium、mac 的预览应用等中很好地查看来自背面的 PDF。从这个意义上说,PDF 格式正确。一般来说,我希望能够使用格式正确的 PDF,因为它们可以被标准 PDF 查看器查看。如果 PDFJS 只能使用在某种更严格意义上正确格式化的 PDF,那么在我看来,这要么是 PDFJS 中的错误,要么是缺乏功能。如果是这种情况,我想要一个 PDFJS 的替代品,我可以尝试使用它。我怀疑情况并非如此,如果我实际上错误地将上传的文件交给 PDFJS,这会导致我遇到的问题。

为了给你更多的背景信息,我的目标是构建一个简单的 html 应用程序,允许用户上传他们的任何 PDF 并查看它。可以在这里看到:'https://github.com/mozilla/pdf.js#online-demo' 它似乎适用于各种 PDF,但是我自己无法使其工作。

特别是,我希望用户能够查看任何可以在标准 PDF 查看器中查看的 PDF,例如网络浏览器(例如:firefox 等)。我希望从用户本地计算机加载 PDF,而不是作为 url 链接给出。我希望这个澄清会有所帮助。如果有任何问题,请告诉我。感谢您的宝贵时间。

【问题讨论】:

    标签: javascript pdfjs


    【解决方案1】:

    TL;DR 跳转到结尾。

    您输出的编码二进制流如这些符号所见,并且随着您使 PDF 变得更加复杂,数学字体、图像和普通嵌入字体将越来越需要它们。可以以 ascii 代码输出它们,只要所有输出都被索引,就可以接受。通过输出为 WEB /Linearized,您的背面代码也更加复杂。

    PDF 的结构并不简单,在包含外部参照表的情况下,您的最小工作示例应该看起来更像这样。

    %PDF-1.7
    %µ¶
    
    1 0 obj
    <</Type/Catalog/Pages 2 0 R>>
    endobj
    
    2 0 obj
    <</Type/Pages/MediaBox[0 0 200 200]/Count 1/Kids[3 0 R]>>
    endobj
    
    3 0 obj
    <</Type/Page/Parent 2 0 R/Resources<</Font<</F1 4 0 R>>>>/Contents 5 0 R>>
    endobj
    
    4 0 obj
    <</Type/Font/Subtype/Type1/BaseFont/Times-Roman>>
    endobj
    
    5 0 obj
    <</Length 63>>
    stream
    q
    BT
    -50 TL
    /F1 12 Tf
    1 0 0 1 70 50 Tm
    (Hello, world!) Tj
    ET
    Q
    
    endstream
    endobj
    
    xref
    0 6
    0000000000 65536 f 
    0000000016 00000 n 
    0000000062 00000 n 
    0000000136 00000 n 
    0000000227 00000 n 
    0000000293 00000 n 
    
    trailer
    <</Size 6/Root 1 0 R>>
    startxref
    405
    %%EOF
    

    这种格式的主要问题是十进制字节地址需要正确,因此大文件中 \n \r\n 和 \r 之间的不同 OS 行结尾可能会大幅改变这些值,例如一个字节错误并且文件已损坏。

    InvalidPDFException 通常意味着以下两件事之一期望/接受 PDF 作为 text.base64 然后将客户端转换为 binary.pdf

    该错误表明二进制扁平数据已被 ascii 处理损坏,可能在传输或接收时未存储为应用程序/pdf 数据,因为 pdf 的部分编码就像 zip 文件一样

    终于

    在讨论中我注意到最后一行脚本说 readAsText() 并且那些基于 ascii 的 PDF 正在工作,同时在不同的浏览器中测试上面脚本的许多变体(试图清除控制台 cmets)我测试过的最简单的解决方案(除了 IE11 不会打球)是用reader.readAsBinaryString(e.target.files[0]) 替换它。但是我建议使用更完整的跨浏览器示例来处理密码等对其他人来说会更好,但如果它适合你,那就足够了。

    【讨论】:

    • 感谢您为我提供另一个测试仪 PDF。我试过了,它适用于我的 PDFJS html 页面。但是我仍然不知道如何修复 html 页面,以便它也可以接受我的其他 PDF。例如,我可以对我的 html 代码做些什么,以便我从背面获得的 PDF 也可以工作?再次感谢。
    • 我认为 PDF 并不“坏”,因为我可以在我的 Mac 上的 Firefox 中很好地打开它们。我有读取 PDF 文件然后将其传递给 PDFJS 代码的代码。我应该对其进行一些预处理以确保其格式正确吗?如果可以,我可以做什么样的预处理?
    • 感谢您迄今为止的帮助。在我看来,如果我的浏览器(firefox、chrome 等)能够阅读 PDF,PDFJS 应该能够阅读 PDF。此外,我的 Mac 上的 hte PDF 查看器“预览”可以很好地阅读 PDF。 PDFJS 无法阅读这些 PDF 的事实是错误还是缺少功能?或者我可以对我的 JS 代码进行简单的修改以使其正常工作?
    • 我可能是错的,但我不认为这是依赖于操作系统的问题。如果您想尝试重现我的问题,我认为您可以将我提供的 HTML 代码放入文件中,然后在任何浏览器中打开该文件,然后尝试查看您的任何 PDF。特别是您可以查看从背面下载的 PDF。如果您设法从背面查看了这样的 PDF,那么也许我的问题确实与我的操作系统有关,但我怀疑不是。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    • 2016-09-01
    • 1970-01-01
    相关资源
    最近更新 更多