Skip to content

Instantly share code, notes, and snippets.

@sergiodxa
Last active May 7, 2024 12:30
Show Gist options
  • Save sergiodxa/e339cc18f34834871497ac35a1353f43 to your computer and use it in GitHub Desktop.
Save sergiodxa/e339cc18f34834871497ac35a1353f43 to your computer and use it in GitHub Desktop.
Dynamically generate a PDF with Remix
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 });
}
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>
);
}
@adilameeq
Copy link

same error

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