Skip to content

Instantly share code, notes, and snippets.

@webshared
Last active September 30, 2022 09:32
Show Gist options
  • Save webshared/dd2e257f669b1a5ca06e4f4514326d3b to your computer and use it in GitHub Desktop.
Save webshared/dd2e257f669b1a5ca06e4f4514326d3b to your computer and use it in GitHub Desktop.
React-Pdf workaround: renders PDF as Blob in browser and display at page + show download link
import React from 'react';
import {
Page, Text, Image, View, Document, StyleSheet,
createElement, pdf, PDFRenderer,
} from '@react-pdf/core';
import blobStream from 'blob-stream';
const Doc = () => (
<Document>
<Page wrap={true}>
<Text fixed={true}>
~ HELLO PDF RENDERER ~
</Text>
</Page>
</Document>
);
class Pdf extends React.Component {
constructor(props) {
super(props);
this.state = {
downloadUrl: null,
}
this.pdfNode = null;
this.setPdfRef = elem => {
this.pdfNode = elem;
};
this.renderPdf = async () => {
if (this.pdfNode) {
// Render the PDF here
const element = <Doc />;
const container = createElement('ROOT');
const node = PDFRenderer.createContainer(container);
PDFRenderer.updateContainer(element, node, null);
const buffer = await pdf(container).toBuffer();
const stream = buffer.pipe(blobStream());
const url = await new Promise((resolve, reject) => {
stream.on('finish', () => {
resolve(stream.toBlobURL('application/pdf'));
});
stream.on('error', reject);
});
this.setState({downloadUrl: url});
this.pdfNode.src = url;
}
}
}
componentDidMount() {
this.renderPdf();
}
render() {
return (
<div>
{this.state.downloadUrl && (
<div><a href={this.state.downloadUrl} download="file.pdf">Download PDF</a></div>
)}
<iframe style={{width: 700, height: 800}} ref={this.setPdfRef}>
</iframe>
</div>
);
}
}
export default Pdf;
@Oosasukel
Copy link

@rpilev, I got it using the lib pdfjs-dist

You should be able to improve this logic, but it is a way that I was able to do haha 😅

1. I transformed the document into a url:

image

image

2. I transformed the url into a canvas passing the desired page, if you have many pages:

image

import workerURL from './pdf.worker.min.es5.data';

var pdfjsLib = require('pdfjs-dist/es5/build/pdf');

interface pdfToCanvasResponse {
  canvas: HTMLCanvasElement | null;
  pages: number;
}

/** This function returns a canvas or undefined if pdfUrl is not valid */
function pdfToCanvas(
  pdfUrl: string | null | undefined,
  pageToDisplay: number
): Promise<pdfToCanvasResponse> {
  return new Promise((resolve) => {
    if (pdfUrl) {
      pdfjsLib.GlobalWorkerOptions.workerSrc = workerURL;

      const loadingTask = pdfjsLib.getDocument(pdfUrl);

      loadingTask.promise.then(function (pdf: any) {
        const pages = pdf.numPages;

        if (pageToDisplay > pages) {
          pageToDisplay = pages;
        }

        pdf.getPage(pageToDisplay).then(function (page: any) {
          const viewport = page.getViewport({ scale: 2 });

          const canvas = document.createElement('canvas');
          const context = canvas.getContext('2d');
          canvas.height = viewport.height;
          canvas.width = viewport.width;

          if (context) {
            const renderContext = {
              canvasContext: context,
              viewport: viewport,
            };

            page.render(renderContext).promise.then(() => {
              resolve({ canvas, pages });
            });
          } else {
            resolve({ canvas: null, pages: 0 });
          }
        });
      });
    } else {
      resolve({ canvas: null, pages: 0 });
    }
  });
}

export default pdfToCanvas;

3. I drew this canvas on another canvas that was in html

image

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment