Search code examples
fetchsveltesveltekitarraybuffer

Sending PDF from a post request in SvelteKit


I have form data that I'm sending to my endpoint with a POST request and I'm trying to create a PDF with puppeteer and send it back as response.

My /generate endpoint code

import { launch } from 'puppeteer';

export async function post({ request }) {
    const browser = await launch({
        headless: true
    });

    const page = await browser.newPage();
    const html = `<div>Test</div>`;
    await page.setContent(html, {
        waitUntil: 'domcontentloaded'
    });

    const pdfBuffer = await page.pdf({
        format: 'A4'
    });

    await browser.close();

    return {
        headers: {
            'Content-Type': 'application/pdf'
        },
        status: 200,
        body: pdfBuffer
    };
}

And the following is my client-side javascript

try {
    const response = await fetch('/generate', {
        method: 'POST',
        // headers: {
        //  'Content-Type': 'application/json'
        // },
        body: JSON.stringify(values)
    });
    const abuffer = await response.arrayBuffer();
    const buffer = Buffer.from(new Uint8Array(abuffer));
    const buff = await sharp(buffer).toFormat('jpeg').toBuffer();
    let base64data = buff.toString('base64');
    
} catch (e) {
    console.log(e);
}

I'm getting a Buffer is undefined.. error trying this code.
Any help is appreciated, thanks


Solution

  • The main problem seems server-side. When you try to return application/pdf you should get the error:

    Body returned from endpoint request handler must be a plain object

    You could send the data as base 64 like this:

    return {
        status: 200,
        body: {
            pdf: pdfBuffer.toString('base64'),
        }
    };
    

    Client:

    const response = await fetch('/generate', {
        method: 'post',
        headers: {
            'Accept': 'application/json',
        },
    })
    
    const json = await response.json();
    
    // Test download
    const link = document.createElement('a');
    link.href = `data:application/pdf;base64,${json.pdf}`;
    link.download = 'puppeteer-pdf.pdf';
    link.click();
    

    If you are going to convert the PDF to an image anyway, I would recommend doing that directly on the server and just return the image.