Search code examples
node.jspdfkit

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client - PDFKIT


I'm trying to convert information from the database to a pdf, that the user can download from my website. I'm new to nodejs and I'm currently changing somethings on an already developed website. The goal is for the user to press a button and download a pdf document. That document should be populated with the information in the database regarding a particular entry on the website.

I'm getting the error "Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client" and don't understand why or how to solve.

"use strict";

let     express             = require('express'),
        router              = express.Router(),
        asyncMiddleware     = require('../utils/asyncMiddleware'),
        auth                = require('../middleware/authentication'),
        // pdf                 = require('html-pdf'),
        blobStream          = require('blob-stream'),
        pdf                 = require('pdfkit'),
        juice               = require('juice'),
        {User, Report}      = require('../models');







router.get('/:reportId?', auth.isLoggedIn, asyncMiddleware( async(req, res) => {

    let reqUser = req.user;
    //get the report
    let report = await Report.findById( req.params.reportId ).populate('ownerManagerId');

    if( !report ) {
        req.flash('error', req.__('flash.error.reportNotFound') );
        return res.redirect('back');
    }

    //check if user on the request is the user of the report or is the group admin stored when the report was generated 
    if(  !reqUser._id.equals(report.ownerId) && !reqUser._id.equals(report.ownerManagerId) && req.user.role !=="admin" ){
        req.flash('error', req.__('flash.error.forbiddenAccess') );
        return res.redirect('back');
    }
   
    //report data
    let data = {
        layout: 'pdf_layout',
        styles: [],
        scripts: [],
        user: reqUser,
        lang: req.lang,
        pageTitle: req.__('pageTitle-calculator-report'),
        reportOwnerManager: report.ownerManagerId,
        reportDate: formatDateInReport( report.createdAt ),
        calcData: report.inputs,
        output: report.outputs
    }

    //add some helper functions to ejs views
    res.locals.formatNum = formatNum;
    res.locals.findInputCorr = findInputCorr;

    res.render('calculadora/relatorioPdf', data, (err1, html)=>{

        //set headers so the file is downloaded instead of shown in browser

        const stream = res.writeHead(200, {
            'Content-Type': 'application/pdf',
            'Content-disposition': `attachment; filename=relatorio-${report.id}.pdf`
        });

        buildPDF(
            (chunk) => stream.write(chunk),
            () => stream.end()
        );

        function buildPDF() {
            const doc = new pdf();
            doc.on('data', dataCallback);
            doc.end('data', endCallback);
            doc.pipe(res);
            doc.end();
        }
    });//render

}))//get

Thank you


Solution

  • I realized that pdfkit was not able to stream the html response to a pdf file and download it.

    I used wkhtmltopdf instead, successfully.