react-pdf: Image rendering on Node backend does not work

Describe the bug I am generating the pdf on the backend using the example from the website await renderToFile(<MyDocument />, ${__dirname}/my-doc.pdf);

but i am unable to use the Image component. I have tried to use external images and also internal images but i see an empty space. I have tried the same code on the frontend with React and the Pdf is generated correctly, i have tried even with the PdfDownloadLink and it correctly renders the image.

To Reproduce

  1. generate an express app with nodejs
  2. generate a route where you return or generate the Pdf
const router = express.Router();

router.post(
  "/api/printTest",
  asyncHandler(async (req: Request, res: Response) => {
    try {
      const { source } = req.body as { source: any};

      const string = await renderToString(<DocumentWithImage source={source} />);
      // or       await renderToFile(<DocumentWithImage source={source} />, `${__dirname}/my-doc.pdf`);

      res.send(string);
    } catch (error) {
    
      res.status(400).send(new Error("PDF Error Generation"));
    }
  })
);

export { router as printRouter};

Expected behavior I should see the image inside the Pdf

Desktop (please complete the following information):

  • OS: [ Windows 10]
  • Browser [ chrome,]
  • React-pdf version [ v2.0.4]

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 3
  • Comments: 19 (9 by maintainers)

Most upvoted comments

I was able to achieve what you want by rendering using the renderToStream function:

// print.tsx

import { renderToStream } from '@react-pdf/renderer'
import express, { Request, Response } from 'express'
import asyncHandler from 'express-async-handler'
import React from 'react'
import { ImageDocument } from '../documents/ImageDocument'

import type { DocumentNode } from '@react-pdf/types'

const router = express.Router()

async function convertDocumentToBuffer(
  document: DocumentNode
): Promise<Buffer> {
  const stream = await renderToStream(document)
  return new Promise((resolve, reject) => {
    let buffers: Uint8Array[] = []
    stream.on('data', data => {
      buffers.push(data)
    })
    stream.on('end', () => {
      resolve(Buffer.concat(buffers))
    })
    stream.on('error', reject)
  })
}

router.post(
  '/api/print',
  asyncHandler(async (req: Request, res: Response) => {
    try {
      const document = await convertDocumentToBuffer(<ImageDocument />)
      res.send(document)
    } catch (error) {
      res.status(400).send(new Error('PDF Error Generation'))
    }
  })
)

export { router as printRouter }

@diegomura I’m able to reproduce the same issue in the latest version 2.0.20 as well. The renderToString does not render the images at all.

Here is a screenshot of the output PDF: Screenshot 2021-10-24 at 1 02 22 PM