Search code examples
reactjspdfpdf.jspdf-viewer

How to render 20% of a pdf with custom pdf viewer created with pdf.js


This is the code that is responsible to get the pdf. It then passes the pdf to the pdf viewer for it to be rendered. I don't want to render the whole pdf. Instead, I want to render just part of the pdf, for example, the first 5 pages, or 20% of the page. The code below uses pdfjs and this code below is available in the PDFJS repo. You can access the entire code via https://github.com/mozilla/pdf.js/blob/master/examples/mobile-viewer/viewer.js

private open (params) {
    let url = params.url
    let self = this
    this.setTitleUsingUrl(url)
    // Loading document.
    let loadingTask = pdfjsLib.getDocument({
      url: url,
      withCredentials: true,
      maxImageSize: MAX_IMAGE_SIZE,
      cMapPacked: CMAP_PACKED
    })
    this.pdfLoadingTask = loadingTask

    loadingTask.onProgress = function (progressData) {
      self.progress(progressData.loaded / progressData.total)
    }

    return loadingTask.promise.then(function (pdfDocument) {
      // Document loaded, specifying document for the viewer.
      console.log(pdfDocument); // The pdf object. picture content below

      // The document is being passed to the viewer for rendering
      // I want to pass just 15% of the document to the user to view
      self.pdfDocument = pdfDocument;
      self.pdfViewer.setDocument(pdfDocument)
      self.pdfLinkService.setDocument(pdfDocument)
      self.pdfHistory.initialize(pdfDocument.fingerprint)
      self.loadingBar.hide()
      self.setTitleUsingMetadata(pdfDocument)
    }

The image below is the structure of the pdf object

enter image description here


Solution

  • I can suggest a package react-pdf. It is a wrapper of pdf.js. The document has props onLoadSuccess as a function with object as an argument. As I know in this object you can find numPages - the total number of pages. You can manipulate this number like Math.floor(0.2*numPages) and render only this number of pages. However, read documentation MB you can find a better solution.

    UPDATE:

    import React, { Component } from 'react';
    import { Document, Page } from 'react-pdf';
    
    class MyApp extends Component {
      state = {
        numPages: null,
      }
    
      onDocumentLoadSuccess = ({ numPages }) => {
        this.setState({ numPages: Math.floor(0.2 * numPages) });
      }
    
      render() {
        const { numPages } = this.state;
    
        return (
          <div>
            <Document
              file="somefile.pdf"
              onLoadSuccess={this.onDocumentLoadSuccess}
            >
              {Array.from({length: numPages}, (v, i) => i).map(i => (
                <Page key={i} pageIndex={i} />
              ))}
            </Document>
          </div>
        );
      }
    }