node.jspdfdownloadfilestreamhtml-pdf

Saving buffer/stream that comes from nodejs server


I am not sure what I am doing wrong.

I have a html content and want to save it as pdf. I use html-pdf (from npm) and a download library http://danml.com/download.html

Actually when I directly save to file or show it as a result I can get the pdf without problem. But I call my webservice method from a js method and I have a stream/buffer as a return value and saving with the 'download' library

Here is my code

pdf.create(html, options).toFile('./mypdf.pdf', function (err, res) {
    if (err) return console.log(err);
        console.log(res);
  });

pdf.create(html,options).toBuffer(function (err, buffer) {
  if (err) return  reject(err);     
      return resolve(buffer);             
 });

//res.setHeader('Content-type', 'application/pdf');
pdf.create(html, options).toStream(function (err, stream) {
  if (err) return res.send(err);
     //res.type('pdf');
   return resolve(stream);// .pipe(res);
 });

I can save the content as a pdf it works fine. but when I try to send stream or buffer, somehow the page is empty. I opened the both pdf files with notepad. There are some differences. For example, probless one is 44kb the other one 78 kb. and the empty one contains also the following lines

%PDF-1.4 1 0 obj << /Title (��) /Creator (��) /Producer (�� Q t 5 . 5 . 1) /CreationDate (D:20190524152156)

endobj

I think toBuffer or toStream method has a problem in my case. Because the stream seems not bad. at least I can see that it is a pdf file (no error, just page is empty)

Anyway, here is my API router

let result = await
routerVoucher.CreatePdfStream(req.query.VoucherCode,req.query.AppName);
res.setHeader('Content-type', 'application/pdf');
res.type('pdf');
//result.pipe(res);
res.end(result, 'binary');

and here is my js consumer

    $.ajax({
            type: "GET",
            url: '/api/vouchers/GetLicensePdf',
            data:data,
            success: function (pdfFile) {

                if (!pdfFile) 
                    throw new Error('There is nothing to download');

                    download(pdfFile,voucherCode + '.pdf', 'application/pdf')

Solution

  • I've solved the problem.

    Firstly I converted buffer to base64

    const base64 = buffer.toString('base64')
    

    and then converted base64 to blob by using the following code

    function base64toBlob (base64Data, contentType) {
    
        contentType = contentType || '';
        var sliceSize = 1024;
        var byteCharacters = atob(base64Data);
        //var byteCharacters = decodeURIComponent(escape(window.atob(base64Data)))
        var bytesLength = byteCharacters.length;
        var slicesCount = Math.ceil(bytesLength / sliceSize);
        var byteArrays = new Array(slicesCount);
    
        for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
            var begin = sliceIndex * sliceSize;
            var end = Math.min(begin + sliceSize, bytesLength);
    
            var bytes = new Array(end - begin);
            for (var offset = begin, i = 0 ; offset < end; ++i, ++offset) {
                bytes[i] = byteCharacters[offset].charCodeAt(0);
            }
            byteArrays[sliceIndex] = new Uint8Array(bytes);
        }
        return new Blob(byteArrays, { type: contentType });
    }
    

    and then

    again I've used my download method (from download.js library) as follow

    download(new Blob([base64toBlob(base64PDF,"application/pdf")]),
             voucherCode + '.pdf', "application/pdf");
    

    then everything is fine :)