【问题标题】:Rendering pdf with pdf.js -- a promise returns unusable result使用 pdf.js 渲染 pdf —— 一个承诺返回不可用的结果
【发布时间】:2019-05-28 14:17:30
【问题描述】:

我对使用 pdf.js 在 html 中渲染 pdf 进行了很多研究和试验,这对于像我这样的菜鸟来说是一项艰巨的任务。

我认为下面的 html 和 JS 的组合可能是一个好的开始,但我仍然卡住了。

HTML部分:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>PDF.js Example</title>
  <script src="build/pdf.js"></script>
  <script src="simple-g-SO.js"></script>

  <style media="screen">
  .button {
    background-color: #333;
    border: none;
    color: white;
    padding: 15px 25px;
    text-align: center;
    font-size: 16px;
    cursor: pointer;
  }

  li:hover {
    background-color: #111;
  }

  ul {
    list-style-type: none;
    margin: 0;
    padding: 0;
    overflow: hidden;
    background-color: #333;
    position: fixed;
    top: 0;
    width: 100%;
  }

  li {
    float: left;
    display: block;
    color: white;
    text-align: center;
    padding: 14px 16px;
    text-decoration: none;
    border-right: 1px solid #bbb;
  }

  </style>
</head>
<body>
  <ul>
    <li><button onclick="leftOnePage()" type="button" class="button" id="left"><</button></li>
    <li><button onclick="rightOnePage()" type="button" class="button" id="right">></button></li>
  </ul>
  <br/>
  <canvas id="pdf"></canvas>
</body>
</html>

加上这个JS代码:

async function renderPdf(pdfDocument,pdfPageN) {
  // Load information from page pdfPageN
  const page = await pdfDocument.getPage(pdfPageN);

  const scale = 1.5;
  const viewport = page.getViewport(scale);

  // Apply page dimensions to the <canvas> element.
  const canvas = document.getElementById("pdf");
  const context = canvas.getContext("2d");
  canvas.height = viewport.height;
  canvas.width = viewport.width;

  // Render the page into the <canvas> element.
  const renderContext = {
    canvasContext: context,
    viewport: viewport
  };
  await page.render(renderContext);
};

async function loadPdf(){
  // load the pdf
  const loadingTask = pdfjsLib.getDocument("http://static.kjuicer.com/varie/fuffa/test.pdf");
  const pdf = await loadingTask.promise;
  return pdf
}

async function initialRenderPdf(){
  const pdfDoc = await loadPdf()
  const renderingPdf = await renderPdf(pdfDoc,pageViewed)
  return pdfDoc
}

pageViewed = 1
myPdf = initialRenderPdf()

//called on left button click
function leftOnePage(){
    if(pageViewed<=1){
        return
    } else {
    pageViewed -= 1
        renderPdf(myPdf,pageViewed)
    }
}

//called on right button click
async function rightOnePage(){
    if(pageViewed>=10){
        return
    } else {
    pageViewed += 1
        await renderPdf(myPdf,pageViewed)
    }
}
async function renderPdf(pdfDocument,pdfPageN) {
  // Load information from page pdfPageN
  const page = await pdfDocument.getPage(pdfPageN);

  const scale = 1.5;
  const viewport = page.getViewport(scale);

  // Apply page dimensions to the <canvas> element.
  const canvas = document.getElementById("pdf");
  const context = canvas.getContext("2d");
  canvas.height = viewport.height;
  canvas.width = viewport.width;

  // Render the page into the <canvas> element.
  const renderContext = {
    canvasContext: context,
    viewport: viewport
  };
  await page.render(renderContext);
};

async function loadPdf(){
  // load the pdf
  const loadingTask = pdfjsLib.getDocument("http://static.kjuicer.com/varie/fuffa/test.pdf");
  const pdf = await loadingTask.promise;
  return pdf
}

async function initialRenderPdf(){
  const pdfDoc = await loadPdf()
  const renderingPdf = await renderPdf(pdfDoc,pageViewed)
  return pdfDoc
}

pageViewed = 1
myPdf = initialRenderPdf()

//called on left button click
function leftOnePage(){
    if(pageViewed<=1){
        return
    } else {
    pageViewed -= 1
        renderPdf(myPdf,pageViewed)
    }
}

//called on right button click
async function rightOnePage(){
    if(pageViewed>=10){
        return
    } else {
    pageViewed += 1
        await renderPdf(myPdf,pageViewed)
    }
}

(它们在 pdf.js 安装程序的根目录中运行,可以下载 here

我不知道我是否忽略了一些与承诺相关的问题,或者理解 pdf.js 的使用错误。

pdf 的第一页将正确显示。一旦我尝试使用右键切换到调用rightOnePage() 的不同页面,它就会向我抛出“TypeError:pdfDocument.getPage 不是函数”。 pdfDocument.getPage 使用loadPdf() 的结果。

然而,loadPdf() 函数应该正确返回 pdf 对象:从 initialRenderPdf() 调用时它可以工作。

我也尝试设置myPdf = initialRenderPdf()[1],将错误更改为TypeError: pdfDocument is undefined,但没有解决。在rightOnePage() 函数中使用myPdf.then(renderPdf(myPdf,pageViewed)) 版本的命令也不行。

我会从一些指导中受益匪浅...

PS:在调用新的页面渲染之前,我可能还需要清除画布。我在实现目标的另一次尝试中遇到了这个问题,但还没有走到那一步。

【问题讨论】:

  • 意识到你缓存的东西 myPdf 是一个承诺,每次使用时都需要等待它,这可能会有所帮助。
  • 它做到了!通过拨打renderPdf(await myPdf,pageViewed) 而不是renderPdf(myPdf,pageViewed),它可以完美运行。谢谢@Roamer-1888!我想知道为什么它在第一次通话时会这样工作,但我的问题现在已经消失了。 :)
  • 第一次调用时,promise 在缓存点const pdfDoc = await loadPdf(); 处等待,然后如您所料,立即成功渲染。您的问题在于页面更改之后没有等待。

标签: javascript pdf promise pdf.js


【解决方案1】:

问题应该在你的:

async function loadPdf(){
  // load the pdf
  const loadingTask = pdfjsLib.getDocument("http://static.kjuicer.com/varie/fuffa/test.pdf");
  const pdf = await loadingTask.promise;
  return pdf
}

getDocument 方法已经返回了一个承诺。为了从中取回数据,您可以简单地执行以下操作:

const pdf = await pdfjsLib.getDocument("http://static.kjuicer.com/varie/fuffa/test.pdf");

更短,你的方法可以直接是这样的:

async function loadPdf(){
  return await pdfjsLib.getDocument("http://static.kjuicer.com/varie/fuffa/test.pdf");
}

【讨论】:

  • 您的代码看起来更漂亮,但结果似乎相同:/ 即:第一页正确加载,但 pdf 对象只有在从 initialRenderPdf() 内部调用时才能正常工作。当对象从 initialRenderPdf() 返回时,它似乎不能正常执行。
【解决方案2】:

getDocument() 有一个需要等待的属性承诺:

const loadingPdfDocument = pdfjsLib.getDocument(typedArray);
const pdfDocumentInstance = await loadingPdfDocument.promise;

【讨论】:

    猜你喜欢
    • 2017-05-16
    • 2017-09-10
    • 2017-10-28
    • 1970-01-01
    • 1970-01-01
    • 2015-11-27
    • 1970-01-01
    • 1970-01-01
    • 2021-06-12
    相关资源
    最近更新 更多