-
-
Notifications
You must be signed in to change notification settings - Fork 891
Frequently Asked Questions
When I'm trying to load a PDF file from an external source, I'm given a message "Failed to load PDF file.".
Most common cause of this issue is a network problem of some kind. Check if the URL you're loading the PDF file from is correct.
If you are sure the URL to the external source you're trying to load is correct, most likely you are experiencing effects of Same-origin Policy. In order to load files from domains other than your own you can do the following:
- Ask domain owner to include your domain in Access-Control-Allow-Origin HTTP header.
- Use a server-side proxy that will go around Same-origin policy limitations (beware: that is a potential security issue, so be sure you know what you're doing before creating one).
If you are using React-PDF like this:
<Document file="http://example.com/document.pdf" />
then nothing will be rendered. Document
component only gives its children (and grandchildren, and great-grandchildren…) a "context" on PDF file you're trying to render. React-PDF can do multiple things with PDF file. You can, for example:
- Render a page
- Render a few pages
- Render document's outline (Table of Contents)
so you need to specify what would you like to do. So to render a page, you need to write:
<Document file="http://example.com/document.pdf">
<Page pageNumber={1} />
</Document>
If you are using React-PDF like this:
<Document file={{ url: 'http://example.com/document.pdf' }} />
then React-PDF thinks you're giving it new (referentially unequal) file
object with every render. Try it in your browser's console!
> ({ url: 'http://example.com/document.pdf' }) === ({ url: 'http://example.com/document.pdf' })
< false // surprise!
To deal with this, file
object must be memoized by setting it in component's state, useMemo
or other similar technique.
const file = useMemo(() => ({ url }), [url]);
return (
<Document file={file} />
);
This way React-PDF will get the same object with each render.
Note: This also applies to options
prop.
Layers of my PDF are misaligned, e.g. the text selection doesn't match actual position of the text. What can I do?
PDF consists of several layers:
- Canvas
- Text layer
- Annotation layer
These layers must be aligned in order for the PDF to look and work well. It can be tempting to auto-resize <canvas>
using CSS - but don't do this! By doing so, you only resize one layer, while leaving the others intact. React-PDF must know the exact size you want to render the document in. Provide scale
, width
, or height
props as desired, and use ResizeObserver
or Window resize event to maintain responsiveness.
To open load a PDF from Base64, you need to need to transform it to Data URL. Don't worry, it's easy!
Here's a sample PDF file in Base64:
JVBERi0xLjIgCjkgMCBvYmoKPDwKPj4Kc3RyZWFtCkJULyA5IFRmKFRlc3QpJyBFVAplbmRzdHJlYW0KZW5kb2JqCjQgMCBvYmoKPDwKL1R5cGUgL1BhZ2UKL1BhcmVudCA1IDAgUgovQ29udGVudHMgOSAwIFIKPj4KZW5kb2JqCjUgMCBvYmoKPDwKL0tpZHMgWzQgMCBSIF0KL0NvdW50IDEKL1R5cGUgL1BhZ2VzCi9NZWRpYUJveCBbIDAgMCA5OSA5IF0KPj4KZW5kb2JqCjMgMCBvYmoKPDwKL1BhZ2VzIDUgMCBSCi9UeXBlIC9DYXRhbG9nCj4+CmVuZG9iagp0cmFpbGVyCjw8Ci9Sb290IDMgMCBSCj4+CiUlRU9G
all you have to do is prepend your Base64 string with data:application/pdf;base64,
. It turns into a valid link. Try and paste the string below into your browser!
data:application/pdf;base64,JVBERi0xLjIgCjkgMCBvYmoKPDwKPj4Kc3RyZWFtCkJULyA5IFRmKFRlc3QpJyBFVAplbmRzdHJlYW0KZW5kb2JqCjQgMCBvYmoKPDwKL1R5cGUgL1BhZ2UKL1BhcmVudCA1IDAgUgovQ29udGVudHMgOSAwIFIKPj4KZW5kb2JqCjUgMCBvYmoKPDwKL0tpZHMgWzQgMCBSIF0KL0NvdW50IDEKL1R5cGUgL1BhZ2VzCi9NZWRpYUJveCBbIDAgMCA5OSA5IF0KPj4KZW5kb2JqCjMgMCBvYmoKPDwKL1BhZ2VzIDUgMCBSCi9UeXBlIC9DYXRhbG9nCj4+CmVuZG9iagp0cmFpbGVyCjw8Ci9Sb290IDMgMCBSCj4+CiUlRU9G
So, how to do this with React-PDF? Like so:
<Document file={`data:application/pdf;base64,${base64String}`}>
<Page pageNumber={1} />
</Document>
React-PDF is capable of downloading partial content, meaning, if have a PDF with a book, but only render its cover, it's smart enough not to download the entire book - provided that PDF is built correctly and the server supports Partial Content.
Rendering multiple pages at once is a compute intensive task and WILL be slow, even on good machines. Use virtualization to only render the pages the user sees.
By default, React-PDF renders PDFs at native pixel density. The higher the pixel density, the more actual pixels need to be rendered on the screen. Modern devices, especially mobile, have higher pixel density.
For example, iPhone has pixel density of 3. Each "1x1px" square is going to be rendered by 9 physical pixels on the screen. So, a typical A4 page (794x1123px), will actually be rendered as 2382x3369px canvas. That's a lot of work, especially for a mobile phone!
You could cap maximum pixel density by passing e.g. Math.min(2, window.devicePixelRatio)
to devicePixelRatio
prop, preventing obscenely high pixel density, while maintaining good looks on most devices.
Some performance decrease after React-PDF is added to your bundle is inevitable. React-PDF uses Mozilla's PDF.js which weighs around 2 MB before compression.
Here are several things you can do to improve this.
Newest versions of Node.js can significantly improve performance of bundlers like Webpack. It works the other way around, too: bundlers like Webpack take advantage of some tricks Node.js can do in the newest versions. It's a good idea to keep them both up to date.
With parallel
option in UglifyJsPlugin, you can use multiple processor cores to do the minifying. This speeds up bundling process by quite a bit.
new webpack.optimize.UglifyJsPlugin({
+ parallel: true,
}),
PDF.js files remain unchanged between builds, so it won't hurt to use caching to prevent UglifyJsPlugin from doing the same job over and over again. This speeds the second and all the next builds.
new webpack.optimize.UglifyJsPlugin({
+ cache: true,
}),