如何使用文件输入在PDFJS中打开本地PDF?

28

我想知道是否有一种方法可以使用input type="file"选择一个PDF文件,并使用PDFJS打开它。


@Basj 所以基本上您只是想看到一个答案,就像下面所示的那样,但是使用来自此GitHub问题的答案代码进行变异?还是有点过于简化了? - Chiel
@Chiel 是的,在此期间,这条评论 显示添加 .promise.then(...) 可以解决它! - Basj
@Basj 如果我没错的话,回答这个问题现在应该不难了,对吧? - Chiel
对,我在开始悬赏时并不知道这一点 ;) - Basj
3个回答

55

您可以使用FileReader将文件对象的内容获取为类型化数组,pdfjs接受该数组 (https://mozilla.github.io/pdf.js/examples/)

//Step 1: Get the file from the input element                
inputElement.onchange = function(event) {

    var file = event.target.files[0];

    //Step 2: Read the file using file reader
    var fileReader = new FileReader();  

    fileReader.onload = function() {

        //Step 4:turn array buffer into typed array
        var typedarray = new Uint8Array(this.result);

        //Step 5:pdfjs should be able to read this
        const loadingTask = pdfjsLib.getDocument(typedarray);
        loadingTask.promise.then(pdf => {
            // The document is loaded here...
        });
                    

    };
    //Step 3:Read the file as ArrayBuffer
    fileReader.readAsArrayBuffer(file);
 
 }

编辑:自从我在2015年写下这篇第一篇答案以来,pdfjs API已经发生了一些变化。更新以反映截至2021年的新API(感谢@Chiel)的更新答案


1
感谢@sam。为了补充这个答案:请参阅此处有关如何使用pdf.js提取文本的信息:https://dev59.com/1XI_5IYBdhLWcg3wDOZC#20522307 - mota
你好。感谢您的回复。不使用文件输入类型是否可能?我在Java中有一个字符串URL和在xhtml中有一个h:inputHidden。谢谢。 - Paladice
1
看起来现在可以使用pdfjsLib了。如果我们导入CDN版本,PDF.js将作为“var pdfjs = pdfjsLib.getDocument(typed_array)”可用。 - rags2riches-prog
1
它对我起作用了。我只需要直接使用PDFJS.getDocument(this.result)。 - Alessandro Gurgel
关于rags2riches和Alessandro的问题:我认为这取决于你如何加载它:当你通过<script>标签加载时,创建快捷方式以访问PDF.js导出。var pdfjsLib = window['pdfjs-dist/build/pdf']; - Rustam A.

15

如果 getDocument().then 不是一个函数:

我想我已经成功解决了使用新的 API 时出现的问题。正如在这个 GitHub issue中所提到的,getDocument 函数现在添加了一个 promise。 简而言之,这段代码:

PDFJS.getDocument(typedarray).then(function(pdf) {
    // The document is loaded here...
});

变成了这样:

const loadingTask = pdfjsLib.getDocument(typedarray);
loadingTask.promise.then(pdf => {
    // The document is loaded here...
});

适应新的API以符合赏金要求,将旧答案调整为以下结果:
//Step 1: Get the file from the input element                
inputElement.onchange = function(event) {

    //It is important that you use the file and not the filepath (The file path won't work because of security issues)
    var file = event.target.files[0];

    var fileReader = new FileReader();  

    fileReader.onload = function() {

        var typedarray = new Uint8Array(this.result);

        //replaced the old function with the new api
        const loadingTask = pdfjsLib.getDocument(typedarray);
            loadingTask.promise.then(pdf => {
                // The document is loaded here...
            });

    };
    //Step 3:Read the file as ArrayBuffer
    fileReader.readAsArrayBuffer(file);

 }

I have created an example below with the official releases of the source code below to show that it is working.

/*Offical release of the pdfjs worker*/
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.5.207/pdf.worker.js';
document.getElementById('file').onchange = function(event) {
  var file = event.target.files[0];
  var fileReader = new FileReader();
  fileReader.onload = function() {
    var typedarray = new Uint8Array(this.result);
    console.log(typedarray);
    const loadingTask = pdfjsLib.getDocument(typedarray);
    loadingTask.promise.then(pdf => {
      // The document is loaded here...
      //This below is just for demonstration purposes showing that it works with the moderen api
      pdf.getPage(1).then(function(page) {
        console.log('Page loaded');

        var scale = 1.5;
        var viewport = page.getViewport({
          scale: scale
        });

        var canvas = document.getElementById('pdfCanvas');
        var context = canvas.getContext('2d');
        canvas.height = viewport.height;
        canvas.width = viewport.width;

        // Render PDF page into canvas context
        var renderContext = {
          canvasContext: context,
          viewport: viewport
        };
        var renderTask = page.render(renderContext);
        renderTask.promise.then(function() {
          console.log('Page rendered');
        });

      });
      //end of example code
    });

  }
  fileReader.readAsArrayBuffer(file);
}
<html>

  <head>
  <!-- The offical release-->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.5.207/pdf.js"> </script>
  </head>

  <body>
    <input type="file" id="file">
    <h2>Rendered pdf:</h2>
    <canvas id="pdfCanvas" width="300" height="300"></canvas>

  </body>

</html>

希望这可以帮到您!如果不能,请留言评论。

注意:

这可能在jsFiddle中无法正常工作。


5

我采用了你的代码,它起作用了!然后我在这里和那里浏览更多提示时,我学到了一种更方便的方法。

您可以使用以下方式获取客户端加载文件的URL

URL.createObjectURL()

它可以减少一级嵌套,您无需读取文件、将其转换为数组等。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接