【问题标题】:Is there a way to combine PDFs in pdf.js?有没有办法在 pdf.js 中组合 PDF?
【发布时间】:2012-04-06 05:31:53
【问题描述】:

我想使用 pdf.js 将 html5 中的现有 pdf 文件合并并从中生成单个 pdf

这可能吗?我该怎么做?

【问题讨论】:

  • 据我了解,pdf.js 是一个使用 HTML5 的 PDF 渲染库,而不是 PDF 生成器。您是否正在考虑在同一个 HTML5 画布中呈现多个 PDF?

标签: javascript html pdf pdf.js


【解决方案1】:

最好先在服务器上合并页面。

【讨论】:

  • 你会为此推荐 tcpdf 吗?
  • java 不是 javascript。我为什么要使用java?我现在用 fpdf 和 fpdi 做到了
  • (为反对票道歉;那是偶然的)正如@druff 所说,JavaScript 不是 Java,但对于繁重的工作负载,一些服务器后端可能是合适的。你有解决方案吗?一些 JavaScript PDF 库被设计为在 node.js 中工作。 Java 和 .Net 还有其他后端。对于 Java Apache 的 PDFBox (pdfbox.apache.org/index.html) 看起来非常健壮。我相信 iText(及其 .Net 变体)现在是用于商业用途的封闭源代码。
【解决方案2】:

合并多个文档并仅将它们与 pdf.js 一起显示是很容易的 - 我只是根据 mozilla 在其存储库中提供的简单 prev/next viewer 示例破解了以下示例。

// If absolute URL from the remote server is provided, configure the CORS
// header on that server.
//
var urls = [
  "http://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf",
  "http://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf",
];

// Disable workers to avoid yet another cross-origin issue (workers need
// the URL of the script to be loaded, and dynamically loading a cross-origin
// script does not work).
//
// pdfjsLib.disableWorker = true;

// In cases when the pdf.worker.js is located at the different folder than the
// pdf.js's one, or the pdf.js is executed via eval(), the workerSrc property
// shall be specified.
//
// pdfjsLib.workerSrc = 'pdf.worker.js';

/**
 * @typedef {Object} PageInfo
 * @property {number} documentIndex
 * @property {number} pageNumber
 */

var pdfDocs = [],
  /**
   * @property {PageInfo}
   */
  current = {},
  totalPageCount = 0,
  pageNum = 1,
  pageRendering = false,
  pageNumPending = null,
  scale = 0.8,
  canvas = document.getElementById("the-canvas"),
  ctx = canvas.getContext("2d");

/**
 * Get page info from document, resize canvas accordingly, and render page.
 * @param num Page number.
 */
function renderPage(num) {
  pageRendering = true;
  current = getPageInfo(num);
  // Using promise to fetch the page
  pdfDocs[current.documentIndex].getPage(current.pageNumber).then(function(page) {
    var viewport = page.getViewport({ scale: scale });
    canvas.height = viewport.height;
    canvas.width = viewport.width;

    // Render PDF page into canvas context
    var renderContext = {
      canvasContext: ctx,
      viewport: viewport,
    };
    var renderTask = page.render(renderContext);

    // Wait for rendering to finish
    renderTask.promise.then(function() {
      pageRendering = false;
      if (pageNumPending !== null) {
        // New page rendering is pending
        renderPage(pageNumPending);
        pageNumPending = null;
      }
    });
  });

  // Update page counters
  document.getElementById("page_num").textContent = pageNum;
}

/**
 * If another page rendering in progress, waits until the rendering is
 * finished. Otherwise, executes rendering immediately.
 */
function queueRenderPage(num) {
  if (pageRendering) {
    pageNumPending = num;
  } else {
    renderPage(num);
  }
}

/**
 * Displays previous page.
 */
function onPrevPage() {
  if (pageNum <= 1) {
    return;
  }
  pageNum--;
  queueRenderPage(pageNum);
}

document.getElementById("prev").addEventListener("click", onPrevPage);

/**
 * Displays next page.
 */
function onNextPage() {
  if (pageNum >= totalPageCount && current.documentIndex + 1 === pdfDocs.length) {
    return;
  }

  pageNum++;
  queueRenderPage(pageNum);
}

document.getElementById("next").addEventListener("click", onNextPage);

/**
 * @returns PageNumber
 */
  function getPageInfo(num) {
    let totalPageCount = 0;

    for (let i = 0; i < pdfDocs.length; i++) {
      let currentCount = pdfDocs[i].numPages;
      totalPageCount += currentCount;
      if (num <= totalPageCount) {
        return {
          documentIndex: i,
          pageNumber: (currentCount - (totalPageCount - num)),
        };
      }
    }

    return false;
  }

function getTotalPageCount() {
  var totalPageCount = 0;
  for (var docIdx = 0; docIdx < pdfDocs.length; docIdx++) {
    totalPageCount += pdfDocs[docIdx].numPages;
  }
  return totalPageCount;
}

var loadedCount = 0;

function load() {
  // Load PDFs one after another
  pdfjsLib.getDocument(urls[loadedCount])
    .promise.then(function(pdfDoc_) {
    console.log("loaded PDF " + loadedCount);
    pdfDocs.push(pdfDoc_);
    loadedCount++;
    if (loadedCount !== urls.length) {
      return load();
    }

    console.log("Finished loading");
    totalPageCount = getTotalPageCount();
    document.getElementById("page_count").textContent = totalPageCount;

    // Initial/first page rendering
    renderPage(pageNum);
  });
}
<!DOCTYPE html>
<html>
<head>
  <base href="https://mozilla.github.io/pdf.js/"/>
  <meta charset="UTF-8">
  <title>Previous/Next example</title>
</head>
<body onload="load()">

<div>
  <button id="prev">Previous</button>
  <button id="next">Next</button>
  &nbsp; &nbsp;
  <span>Page: <span id="page_num"></span> / <span id="page_count"></span></span>
</div>

<div>
  <canvas id="the-canvas" style="border:1px solid black"></canvas>
</div>

<script src="build/pdf.js"></script>

</body>
</html>

为了在发送正确 CORS-Header 的服务器上没有可靠的测试文档,本示例简单地合并了默认文档的两个副本。如果您在自己的服务器上执行此操作,您当然可以通过将托管在同一域下的任何文档添加到 urls 数组来添加它们。

【讨论】:

  • 太棒了,很高兴看到一个实际的解决方案
  • 我很高兴:D 无论如何,项目需要这个作为概念验证,所以不客气。图书馆的api documentation 可怕地不存在——但是盯着他们的代码看足够长的时间有时会让我最终到达某个地方。
  • 如果页面长度可变并且加载了两个以上的文档,则上面的 getPageInfo 方法不起作用。 This updated method 工作。
猜你喜欢
  • 2012-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-02
  • 2013-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多