'How can I print a PDF client side that was received from my server?

So I'm very new to generating PDFs from the server side as I have generally always created them from the client side. I decided to migrate to creating them strictly server side because I believe there is more flexibility doing it this way. One thing that I have been struggling with lately is that I'm trying to generate a PDF from the server and then retrieve the data on the client side and be able to print it from there.

I'm using the pdfmake library to generate my PDFs on the server. You can see that I'm using a get request to retrieve the generated PDF here:

server.get(`/api/print_paper_letter`, bodyParser.urlencoded({extended: false}), async (req,res) => {
            try {
                const doc = await PrintPaperLetter(req.body.pdf_obj);
                res.type('application/pdf');
                res.send(doc);
            } catch (e) {
                console.error(`api.print_paper_letter: ${e}`);
                res.sendStatus(400);
            }
        });

And I'm generating the PDF from another file here:

PrintLetter.js

const PdfPrinter = require('pdfmake');
import {PaperLetterNormal} from '../../components/PDFTemplates';

const fonts = {
    Helvetica: {
        normal: 'Helvetica',
        bold: 'Helvetica-Bold',
        italics: 'Helvetica-Oblique',
        bolditalics: 'Helvetica-BoldOblique'
      }
}

export const PrintPaperLetter = async (pdf_obj) => {
    return new Promise(async(resolve,reject) => {
        try {
            const printer = new PdfPrinter(fonts);
            const definition = PaperLetterNormal(pdf_obj);
            const pdf = printer.createPdfKitDocument(definition);
            let chunks = [];
            pdf.on('data', chunk => chunks.push(chunk));
            pdf.on('end',() => resolve(Buffer.concat(chunks)));
            pdf.end();
        } catch (e) {
            console.error(`PaperLetters.PrintPaperLetter: ${e}`);
            reject(e);
        }
    })
}

When I make the call to retrieve the PDF data from the client side I end up getting some sort of garbage data, but I'm not sure how I would be able to print this.

Client side code:

const pdf_obj = {
  .
  .
  .
}

$.post('/api/print_paper_letter',{pdf_obj: pdf_obj},(res) => {
                    if(!res){
                        console.error(`there was an issue retrieving this pdf doc`)
                    }else{
                        console.log({res});
                    }
                })

The response on the client side looks like this:

%PDF-1.3
%ÿÿÿÿ
9 0 obj
<<
/Type /ExtGState
/ca 1
/CA 1
>>
endobj
11 0 obj
<<
/Type /ExtGState
/CA 1
>>
endobj
13 0 obj
<<
/Type /ExtGState
/ca 1
>>
endobj
8 0 obj
<<
/Type /Page
/Parent 1 0 R
/MediaBox [0 0 595.28 841.89]
/Contents 6 0 R
/Resources 7 0 R
>>
endobj
7 0 obj
<<
/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
/ExtGState <<
/Gs1 9 0 R
/Gs2 11 0 R
/Gs3 13 0 R
>>
/XObject <<
/I1 5 0 R
>>
/Font <<
/F1 10 0 R
/F2 12 0 R
>>
>>
endobj
6 0 obj
<<
/Length 2896
/Filter /FlateDecode
>>
stream
xÍ]ÛrÇ
}߯P»ÑúR¥âíÄ?¤*±Þ\~Ë\*J*QUòû9îλ i.d¦¤
û hà}M_ï¿t¡ÔÇ´ý¼ùæ/4ýåËæßÒ¼GjCõIòÔìå?Ðôý¿6:üÔ7ßïþû·íîÏ?|;m¿lö?ÿeûÏÍÝ3Þâ9¾ý°<§^8uÜËôø¿§òôánóó{V|ço¦üËôáÇÍï><K²§q«¦\h¥¦êmô4;ÐB76,ï[½Nï«ÞLßËîfªx QMâ
ìD#pSjMjºöT«gÄ
Ö·Àî9=ÑqT8ÉSømkÇк
ÂÁ5º[ÙEà*§ª¾ÛQf¨¾^[2§æ@·ù¿Eí;-üû1´rco½¯Ù0ê]ÝÛë×%ëRCgëØA-¾[&Þ,5þâ®ÊV¦ÿm~þ·èïøþqGYÉx>o´éúÁ?Öýø?}÷Gëg±~þtu­{Q×#FÃÞÛô÷ÎÜ8'.ÍÅûn%
­H·GüÖÂ\Íh©UrÄáÂãcÕÈÂ
þÐ_ͬ0¯ÒhtNÝhA²¡Zêà+Û4[ÉI{½oÀS¬w{jÔê>Z·«In©IÆ÷Ð%m%Bà\/K á°#»&xHù¤£;¸QùãͤQláwª§ó¬æy2é[RÎ]ÏûVBèt­x¦¶
{D¼kOàÂOô°nà´Þâ{â1IGêÅ%9æãahÁzº¯{Æ'!@É5isû?öá2ÌËbB§n³þ²f39F´ÚÕ!D'¸Üñ[Ù\j,P³Äj ­ÙÝÏxëÇígD§2rÐIñé|¶å'Ë´ î§kÁÉpÑ©ÊóÉìH0p××XoìÉ¡yºÝ\?`UJ¤Ýë¿´ÉX®æD|dν5$I˹ßþ°:GüÒEgÒ;0qfIª0HdRÏLa(bÌä0Ý*%Ñîàòg¹
¨~!U-ÕÞ²®ï
.
.
.

If someone could explain to me what I'm looking at in terms of the response, and if it's possible to convert this in a way to then print it on the client side, that would be amazing. Please let me know if you need me to add more to my post. TIA!



Solution 1:[1]

When you send a pdf response, you are sending a blob/buffer to the front-end, so you'll need to capture that in the front-end to display/download the content.

if you want to immediately prompt for download, add res.attachment(filename) to your express function.

EXPLANATION:

res.attachment() does the same as the native node response.setHeader() command. It sets the content-disposition header property to attachment, additionally setting the fil-name, if supplied with one.
After that, to actually serve the file, you call the res.send() method to end the process and send the response, as you do with any request.

Alternatively, if you want to render the file on the client you will need to use a compatible element like the (relatively new) HTML object, or another compatible element.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1