javascriptnode.jsfetchpdfmake

Error when using fetch method and NodeJs route


I got an issue using fetch method in JavaScript with a NodeJS routing.

My JS code :

fetch(url, {
  method: 'POST',
  headers: {
    'Accept': 'application/json, text/plain, */*',
    'Content-Type': 'application/json'
  },
  credentials: 'same-origin',
  body: JSON.stringify({ ids: arrayIds })
}).then(function(response) {
  return response.json();
}).then(function(data) {
  if (data.reload) {
    document.location.reload();
  } else if (data.url) {
    document.location.href = data.url;
  }
});

My NodeJS route :

function _postMultiplePrint(request, response) {
  var fonts = {
        Roboto: {
          normal: 'public/fonts/OpenSans-Regular.ttf',
          bold: 'public/fonts/OpenSans-Bold.ttf',
          italics: 'public/fonts/OpenSans-Italic.ttf',
          bolditalics: 'public/fonts/OpenSans-BoldItalic.ttf'
        }
      },
      printer = new PdfPrinter(fonts),
      docDefinition, pdfDoc;

  docDefinition = {
    content: [
      {
        text: 'This paragraph fills full width, as th'
      }
    ],
    pageSize: 'A4',
    pageMargins: [72, 72],
    footer: {},
    background: {}
  };

  pdfDoc = printer.createPdfKitDocument(docDefinition);
  response.setHeader('Content-type', 'application/pdf');
  response.setHeader('Content-disposition', 'inline; filename="book.pdf"');
  pdfDoc.pipe(response);
  pdfDoc.end();
  response.send(JSON.stringify({ reload: false, url: '' }));
}

My issue : my book.pdf is not loaded in the page when I'm not using fs to write it.

It works with this code but I write files on the server and I don't want to do that :

function _postMultiplePrint(request, response) {
  var fonts = {
        Roboto: {
          normal: 'public/fonts/OpenSans-Regular.ttf',
          bold: 'public/fonts/OpenSans-Bold.ttf',
          italics: 'public/fonts/OpenSans-Italic.ttf',
          bolditalics: 'public/fonts/OpenSans-BoldItalic.ttf'
        }
      },
      printer = new PdfPrinter(fonts),
      docDefinition, pdfDoc;

  docDefinition = {
    content: [
      {
        text: 'This paragraph fills full width, as th'
      }
    ],
    pageSize: 'A4',
    pageMargins: [72, 72],
    footer: {},
    background: {}
  };

  pdfDoc = printer.createPdfKitDocument(docDefinition);
  pdfDoc.pipe(fs.createWriteStream('./public/uploads/book.pdf'));
  pdfDoc.end();
  response.send(JSON.stringify({ url: '/uploads/book.pdf' }));
}

Solution

  • Each HTTP request can have one and only one response.

    Your JS makes an HTTP request. Your server-side code then tries to response with PDF (response.setHeader('Content-type', 'application/pdf'); response.setHeader('Content-disposition', 'inline; filename="book.pdf"'); pdfDoc.pipe(response); pdfDoc.end();) and JSON (response.send(JSON.stringify({ reload: false, url: '' }));).

    That's two responses. That won't work.

    What's more, the Content-disposition will be ignored because it is a request initiated by Ajax, not by regular browser navigation.