-
-
Save deavial/4962dabac5aed87ee4ae3590665b16c8 to your computer and use it in GitHub Desktop.
Dynamically generate a PDF with Remix
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { renderToStream } from "@react-pdf/renderer"; | |
import ReactDOMServer from "react-dom/server"; | |
import { EntryContext, Headers, RemixServer, Request, Response } from "remix"; | |
import PDF, { loader } from "./pdfs/my-pdf.server"; | |
async function handlePDFRequest(request: Request, headers: Headers) { | |
// get the data for the PDF | |
let response = await loader({ request, context: {}, params: {} }); | |
// if it's a response return it, this means we redirected | |
if (response instanceof Response) return response; | |
// set the correct content-type | |
headers.set("Content-Type", "application/pdf"); | |
// render the PDF to a stream | |
let stream = await renderToStream(<PDF {...response} />); | |
// wait for the stream to end and transform it to a Buffer | |
let body: Buffer = await 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); | |
}); | |
// renturn the response | |
return new Response(body, { status: 200, headers }); | |
} | |
export default async function handleRequest( | |
request: Request, | |
status: number, | |
headers: Headers, | |
remixContext: EntryContext | |
) { | |
if (new URL(request.url).pathname === "/my-pdf.pdf") { | |
return await handlePDFRequest(request, headers); | |
} | |
headers.set("Content-Type", "text/html; charset=utf-8"); | |
let markup = ReactDOMServer.renderToString( | |
<RemixServer context={remixContext} url={request.url} /> | |
); | |
return new Response("<!DOCTYPE html>" + markup, { status, headers }); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export let loader: LoaderFunction = async ({ request }) => { | |
let user = await authenticator.isAuthenticated(request); | |
if (!user) return redirect("/"); | |
let data = await api(user.token).getDataForThePDF(); | |
return { data } | |
}; | |
export default function PDF({ data }: Props) { | |
return ( | |
<Document title="Title"> | |
<Page | |
size="A4" | |
style={{ | |
paddingTop: 48, | |
paddingLeft: 72, | |
paddingRight: 48, | |
paddingBottom: 72, | |
}} | |
> | |
// here you can use data and React PDF components to generate the PDF | |
</Page> | |
</Document> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment