Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
To preview a PDF with Node.js and Express, create a dedicated GET route that sends the PDF bytes as application/pdf with Content-Disposition: inline, then navigate to that route or embed it in an iframe. Use res.sendFile() for a trusted file on disk or send a Buffer after setting its content type; do not use res.download() for the preview route because it sets an attachment disposition. Inline viewing is best effort: the browser, its settings, and your delivery stack can affect whether the PDF opens, downloads, or is handed to another application.
Choose direct viewing or an embedded preview
Both approaches use the same Express endpoint and depend on the browser’s PDF handling. Direct navigation opens the PDF route in its own tab or window. An iframe keeps the preview within your page. Whichever you choose, provide a normal link to the PDF route as a fallback for cases where the embedded viewer cannot display it.
| # | Preview | Product | Price | |
|---|---|---|---|---|
| 1 |
|
PDF Viewer And Reader | $2.50 | Buy on Amazon |
| 2 |
|
PDF Reader and PDF Viewer - PDF Creator | Buy on Amazon | |
| 3 |
|
PDF Reader for Fire Tablet | $2.99 | Buy on Amazon |
| 4 |
|
PDF Reader, PDF Viewer, PDF Editor- file document | $6.85 | Buy on Amazon |
| 5 |
|
My PDF Viewer | Buy on Amazon |
| Pattern | Use it when | What to provide |
|---|---|---|
| Direct navigation | The PDF should occupy its own tab or be opened from a button or link. | A link to the preview route. |
| Iframe | The PDF preview belongs inside a document details or review page. | An iframe with a descriptive title, plus a separate link outside it. |
Express’s file-transfer API can serve the file, while the browser’s built-in viewer may handle the PDF. MDN notes that an iframe can display a PDF through that viewer, but PDF iframe embedding has no child fallback content when display fails, so keep an independent link available: MDN: The Inline Frame element.
Build a secure Express preview route
The route should accept an application-level document identifier, check that the current user may access that document, and map the identifier to a server-controlled file path. Do not join unchecked request input directly into a filesystem path. Express warns about user-derived paths; its root option can constrain a relative path to a fixed root directory, but authorization and identifier validation still belong to the application.
#1 Best Overall
- PDF Viewer And Reader Information:-
- - Open Drawer And Documents File List Show.
- - Recently Read File Open Floating Button And Show Drawer List.
- - Last Added File Is Add Automatically add And Read.
- - Folder View open PDF File Internal Storage And SD Crad Storage.
Serving an authorized file from disk
This example assumes your application implements findAuthorizedPdfPath. That function must authorize the request and return a trusted absolute path, or return no path if the document is unavailable to the requester.
app.get('/documents/:id/preview', async (req, res, next) => {
try {
const filePath = await findAuthorizedPdfPath(req.params.id, req.user);
if (!filePath) return res.sendStatus(404);
res.type('application/pdf');
res.set('Content-Disposition', 'inline; filename="document.pdf"');
res.sendFile(filePath, (err) => {
if (err && !res.headersSent) next(err);
});
} catch (err) {
next(err);
}
});
Replace the authorization function with your own database or storage lookup; it is intentionally not a drop-in function. Avoid revealing whether a document exists to a user who is not allowed to access it. If you prefer a fixed root, configure an absolute trusted directory and pass a validated relative filename to sendFile; Express documents path containment behavior for its root option in the sendFile documentation.
res.sendFile() infers the content type from the extension, but setting application/pdf explicitly makes the preview intent clear. Its callback runs when the transfer completes or errors; if the response has already started, forwarding the error to normal middleware may not be able to replace the response. The example therefore calls next(err) only before headers have been sent.
Rank #2
- PDF Reader
- PDF Viewer
- PDF Creator
- Image to PDF
- PDF to Image
Serving a PDF already in memory
If a PDF is already held in a Buffer, explicitly set its media type and inline disposition before sending it. Express documents that Buffer responses otherwise default to application/octet-stream unless a type has been set.
app.get('/documents/:id/preview-buffer', async (req, res, next) => {
try {
const pdfBuffer = await loadAuthorizedPdfBuffer(req.params.id, req.user);
if (!pdfBuffer) return res.sendStatus(404);
res.type('application/pdf');
res.set('Content-Disposition', 'inline; filename="document.pdf"');
res.send(pdfBuffer);
} catch (err) {
next(err);
}
});
As with the disk example, loadAuthorizedPdfBuffer represents application-specific authorization and retrieval. Make sure the bytes really are a PDF; headers cannot turn unrelated data into a valid document.
Set the response headers for preview behavior
The media type tells the client what kind of content it received. Content-Disposition indicates whether the response should be handled normally or presented as an attachment. RFC 6266 defines inline as normal processing according to the media type and attachment as an instruction to save the response. Its wording is: “On the other hand, if it matches “inline”, this implies default processing.” See RFC 6266, Section 4.2.
Rank #3
- PDF Reader for Fire Tablet
- ✔Fast PDF Viewer
- ✔Simple List of PDF Files
- ✔Share and Print PDF
- ✔55 Different Themes
A filename in the disposition header is supplementary; it does not force inline display. Generate it safely rather than inserting untrusted text into a response header. For a route intended to preview a PDF, use a stable name such as document.pdf. You may omit the disposition header and rely on normal media-type handling, but an explicit inline value makes the route’s intent clear.
Do not use res.download() for the preview route. Express documents it as setting Content-Disposition: attachment, which usually produces download behavior rather than a browser preview. It remains appropriate for a separate download action. See the Express res.download() documentation.
Embed the preview with an accessible fallback
Use the route as the iframe’s src and give the frame a title so its purpose is clear. Put a separate link outside the iframe; a user can open the PDF directly if the embedded viewer is unavailable.
Rank #4
- PDF Reader
- PDF Viewer
- PDF Editor
<iframe
src="/documents/123/preview"
title="PDF preview"
width="100%"
height="720"
></iframe>
<p><a href="/documents/123/preview">Open the PDF separately</a></p>
A sandboxed iframe can prevent the browser’s built-in PDF viewer from loading. Do not add a restrictive sandbox attribute without checking the effect on the browsers you support. The MDN iframe reference describes the viewer and iframe behavior.
If the PDF route requires a login cookie, the iframe must be able to send the relevant credentials under your site’s cookie and browser policies. For a cross-origin route, account for the actual authentication, CORS, and framing policies configured by your application. There is no universal cross-origin setup established for every deployment; verify the policies on your own endpoint rather than assuming an iframe will be permitted.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minuteCheck browser capability and delivery behavior
An inline disposition is a request for normal media-type processing, not a promise that every client will render the PDF in place. The browser may lack an inline viewer, the user may have changed PDF handling preferences, or the deployment layer may alter delivery behavior. MDN documents navigator.pdfViewerEnabled as a read-only indication of whether the browser can display PDFs inline when navigating to a PDF: MDN: Navigator.pdfViewerEnabled.
Best Value
- Lightweight And Fast
- Convenient And Efficient
- Free To Use
- Simple Interface
- Stable Performance
if ('pdfViewerEnabled' in navigator && !navigator.pdfViewerEnabled) {
// Keep the open or download link visible; do not assume inline display.
}
Treat this as a capability hint, not a guarantee that a particular iframe or user configuration will behave identically. Preserve the direct link whether or not you check the property. If inline viewing is unavailable, the PDF may be downloaded and handled externally.
Byte ranges and larger PDFs
Express’s sendFile option acceptRanges defaults to enabled. HTTP byte-range requests let a client request part of a resource and receive a partial response; this can support viewers that fetch portions of a PDF. It does not guarantee faster loading in every setup. A reverse proxy, cloud storage layer, or other intermediary can affect whether range requests reach the file source as expected. If partial delivery matters to your application, test through the same production path your users will use. See MDN: HTTP range requests and the Express sendFile options.
Troubleshoot a PDF that downloads or fails to appear
- The route downloads instead of previewing: Look for
res.download()or a response header containingContent-Disposition: attachment. Use a preview route withinlineor omit the disposition, and verify the response has the PDF media type. Browser settings can still choose download behavior. - The browser shows a generic file or cannot parse it: Confirm the response is actual PDF bytes and that
Content-Typeisapplication/pdf. A Buffer response needs its type set explicitly; Express otherwise usesapplication/octet-stream. - The iframe is blank or blocked: Open the preview URL directly to separate iframe-policy problems from file-serving problems. Check the frame’s
sandboxsetting and your application’s framing policy, then use the separate link as a fallback. - The route returns 404: Verify that the document identifier maps to an existing file and that the authorization lookup returns a path for this user. Avoid fixing this by trusting a raw path from the URL.
- The route errors after starting a transfer: A file-transfer error after headers or bytes have been sent cannot necessarily be converted into a clean error response. Log it and ensure the handler does not attempt to send a second response.
- The viewer loads slowly or cannot seek: Check whether range requests survive your proxy or storage layer and test with the production delivery path. Express enables range support for
sendFileby default, but the full stack determines the result. - A cross-origin embed fails despite a working direct URL: Inspect the actual authentication, CORS, cookie, and framing rules for both origins. Configure only the access needed for the intended embedding flow.
Or skip the browser setup
If your goal is to capture a web page as an image or PDF rather than serve an existing PDF from Express, ScreenshotNeo offers a one-request screenshot API and an MCP server for AI agents. It is a different job from delivering your own PDF route; it does not replace the authorization and serving pattern above.
Example using cURL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for the request options. Cookie banners, newsletter popups, and chat widgets are removed before capture; bot checks, blank pages, failed loads, and cache hits are not billed. Its MCP server lets AI agents use screenshot tools. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Sign up for 1,000 free screenshots a month with no card.
Test the route before you rely on it
- Request the preview URL as an authorized user and confirm it returns a successful response containing PDF bytes.
- Inspect the response headers: confirm
Content-Type: application/pdfand thatContent-Dispositionis inline or absent, not attachment. - Open the URL directly and then try the iframe in each browser and device your application supports.
- Test an unauthorized document ID, an unknown ID, and a missing file to check that access control and error handling behave as intended.
- If serving from a proxy or object store, check range-request behavior and framing or authentication policies through that production path.
These checks validate your deployment rather than guaranteeing identical behavior across browser settings or external delivery layers.
Frequently Asked Questions
Can I preview the same PDF and also offer a download?
Yes. Keep a preview route that serves the PDF with inline handling and a separate download action that deliberately uses attachment behavior.
Does `navigator.pdfViewerEnabled` guarantee an iframe will show the PDF?
No. It indicates inline PDF capability when navigating to a PDF; it does not guarantee identical behavior for every embed, setting, or deployment.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

