1

i'm creating a PDF with node.js and this package : https://github.com/devongovett/pdfkit

My problem is that when i download the pdf on the browser it is totaly blanck... server-side code :

    PDFDocument = require('pdfkit');

function creaEtichetta(req, res){
    doc = new PDFDocument
        size: 'a4'
        bufferPages: true



    doc.addPage().fontSize(25).text('Here is some vector graphics...', 100, 100);

    doc.save()
   .moveTo(100, 150)
   .lineTo(100, 250)
   .lineTo(200, 250)
   .fill("#FF3300");

   doc.addPage().fillColor("blue").text('Here is a link!', 100, 100).link(100, 100, 160, 27, 'http://google.com/')

    doc.pipe(res);
    doc.end();
}
exports.creaEtichetta = creaEtichetta;

client-side code :

var data = {};
    data.azione = "getEtichettaProdotto";

    //Scarico i dati anagrafica
    $.ajax({
        type: 'POST',
        data: JSON.stringify(data),
        contentType: 'application/json',
        url: 'http://46.101.209.16/endpoint',                       
        success: function(etichettas) {
            var blob=new Blob([etichettas]);
            var link=document.createElement('a');
            link.href=window.URL.createObjectURL(blob);
            link.download="Label"+".pdf";
            link.click();
        }//SUCCESS
    });

sorry for bad english, i'm italian

Alessandro Zago
  • 793
  • 3
  • 12
  • 33

2 Answers2

2

It could be that the binary characters in your pdf aren't being correctly coded in the transfer, which would explain why locally its ok but not when transferred - pdfs are a mix of ascii and binary characters, and if the binary is corrupted it seems that you get a blank pdf.

That's likely to be a browser side issue, this approach worked for me: https://stackoverflow.com/a/27442914/2900643

Coupled with this: https://stackoverflow.com/a/33818646/2900643

EDIT: Better still use: https://github.com/eligrey/FileSaver.js/

Server:

var doc = new PDFDocument();
doc.pipe(res);
doc.circle(280, 200, 50).fill("#6600FF");
doc.end();

Browser:

angular.module('app')
.service('PdfService', function($http) {
  var svc = this;

  svc.getPdf = function() {
    return $http.get('/getpdf/', { responseType : 'arraybuffer' });
  };
});

angular.module('app')
.controller('PdfCtrl', function($scope, PdfService) {

  $scope.getPdf = function() {
   PdfService.getPdf().success(function(data) {
    var fileName = 'hello.pdf';
    var pdf = new Blob([data], {type : 'application/pdf'});
    saveAs(pdf, fileName);
   })
 };
});
Community
  • 1
  • 1
MikeH
  • 707
  • 5
  • 3
  • "Uncaught ReferenceError: svc is not defined" what is svc? – Alessandro Zago May 09 '16 at 11:00
  • 1
    I'm using angular, and I've split this over a service (svc) and controller - I've added a bit more to the code example to make this clear. But if you're not using angular its the responseType of arraybuffer and the saveAs utility which are the main things you need. – MikeH May 14 '16 at 09:27
1

I was running in the same issue but without any client-side code involved. So this issue isn't simply client-side. Obviously, the server-side response PDFKit is piping into isn't encoding "binary" as requested by PDFKit, but applying "utf8".

Sadly, as of today there is no way of assigning some default encoding to the stream provided by ServerResponse. See https://github.com/nodejs/node/issues/14146

In my case I was working around this issue for now by collecting chunked output from PDFKit and writing at once. Instead of

var doc = new PDF();

res.type( "pdf" ).attachment( "test.pdf" );
doc.pipe( res );

I am using this:

var doc = new PDF();

res.type( "pdf" ).attachment( "test.pdf" );

var buffers = [];
doc.on( "data", function( chunk ) { buffers.push( chunk ); } );
doc.on( "end", function() {
    res.end( Buffer.concat( buffers ), "binary" );
} );

This comes with a disadvantage: since all PDFs are cached in memory this code has an impact on server side memory consumption when it comes to high number of simultaneous requests or to generating huge PDF files.

Confusingly, trying to hand over PDFKit output chunk by chunk didn't work again:

var doc = new PDF();

res.type( "pdf" ).attachment( "test.pdf" );

doc.on( "data", function( chunk ) { res.write( chunk, "binary" ); } );
doc.on( "end", function() { res.end(); } );
Thomas Urban
  • 4,649
  • 26
  • 32