¡No te pierdas las próximas publicaciones!

thumbnail

Te puedes desuscribir en cualquier momento.

cover

Generando un PDF con Remix y fs.readFile()


En el artículo anterior entregamos un archivo PDF con Response y Remix.

En este post vamos a conseguir el PDF desde una carpeta de almacenamiento y vamos a leerlo, convertirlo en streams y devolverlo para que sea entregado:

Primero veamos una versión con una función que podemos usar en cualquier loader:

/app/utils/pdf/

const getPDF = (pdfId: string) => { const pathToFile = path.join(__dirname, "..", `pdfs/${pdfId}.pdf`); return fs.createReadStream(pathToFile); };

Pero claro que también podemos hacerlo todo directamente en el loader:

/app/routes/pdf/$name

async function loader({ params }) { const pdfId = params.id; const pathToFile = path.join(__dirname, '..', `pdfs/${pdfId}.pdf`); const pdfStream = fs.createReadStream(pathToFile); return new Response(pdfStream, { status: 200, headers: { 'Content-Type': 'application/pdf', 'Content-Disposition': 'attachment;filename="invoice.pdf"', }, }); }

Por último te dejo un código que yo uso, donde los PDF vienen de Firebase, pues me es más fácil y ordenado tener estos archivos en un almacenamiento dedicado como un Bucket de Google:

app/routes/pdf/$pdfId

export const loader: LoaderFunction = async ({ request, params }) => { const url = new URL(request.url); // aqui puedes leer algún token por seguridad... const fileName = params.name; if (!fileName) return; const pdfStream = await getFileStream(fileName); // firebase stream return new Response(pdfStream, { status: 200, headers: { "Content-Type": "application/pdf", "Content-Disposition": 'attachment;filename="guía.pdf"', }, }); };

Observa los headers, el Content-Disposition es importante para la descarga del archivo.

Y esta es la función de Firebase:

app/utils/firebase.ts

export const getFileStream = (fileName: string): ReadableStream<any> => { return getStream(ref(storage, `fixtergeek.com/pdfs/${fileName}.pdf`)); };

Espero que esto te sea útil. Abrazo. Bliss.

Remix docs

Cómo entregar archivos con Remix

meta cover

Te explico qué es Closure en JavaScript

Checa este otro Post

meta cover

Fetch API explicada

Checa este otro Post

¡Nuevo curso!

Animaciones web con React + Motion 🧙🏻