Sending a PDF through Express Response yields an empty PDF document

Currently facing an issue while attempting to generate a PDF within a Lambda function using the .pipe() function from PDF Kit. The downloaded PDF appears blank, although I have managed to display content by converting the PDF to a base64 string. However, this method may not be sustainable as the PDF size and number of requests increase.

I aim to utilize .pipe() as suggested in various guides. Below is the code snippet that produces a blank PDF. I have tried setting both responseType: 'blob' and responseType: arraybuffer on my client side, but both result in empty files being opened.

let pdf = new PDFDocument();
pdf.text("hello world", 50, 50);

res.setHeader("Content-Type", "application/pdf");
res.setHeader(
  "Content-Disposition",
  `attachment; filename=test.pdf`
);
res.status(200);

pdf.pipe(res);
pdf.end();

Although this method successfully downloads a PDF with the text "hello world," it is not practical due to performance and memory constraints.

let chunks = [];    
let pdf = new PDFDocument();

pdf.text("hello world", 50, 50);

pdf.on("data", data => {
  chunks.push(data);
});

pdf.on("end", () => {
  res.setHeader("Content-Type", "application/pdf");
  res.setHeader(
    "Content-Disposition",
    `attachment; filename=test.pdf`
  );
  res.status(200);
  const result = Buffer.concat(chunks);
  res.send(
    "data:application/pdf;base64," + result.toString("base64")
  ); 
});

pdf.end();

Upon inspecting the contents of both PDF files generated using the above approaches, it was noticed that the actual content differed significantly. This distinction was also observed in the raw response logged in Chrome. While I won't provide the entire file contents here, the following snippets highlight the disparity:

Blank PDF

stream
xe;
0=Żg )-*7na'cpFǦ<yԛ_[d1>zӰ1Cͻa} .dJ,ptU*
endstream

Working PDF

stream
xœeŒ;
€0û=Å»€šÍg£ )-ì„íÄ*ÎÂû7na'ÃcŠÇpFǦ<yÔ›â_[ô‹Œd1„>ŒzÓ°1ØC³Œ’¤Í»œØa––±«d³J,pt§Ué ÝÎ*
endstream

While I am not well-versed in encoding, it is apparent that there are differences in how the two files are encoded, indicating a potential oversight in setting configurations in Express.

Answer №1

After encountering an issue, a solution was implemented by converting the stream to base64 and then decoding it on the client side.

The following Express function was utilized:

const { Base64Encode } = require("base64-stream");

let pdf = new PDFDocument();

pdf.text("hello world", 50, 50);
res.setHeader("Content-Type", "application/pdf");
res.setHeader(
  "Content-Disposition",
  `attachment; filename=test.pdf`
);

res.status(200);
pdf.pipe(new Base64Encode()).pipe(res);
pdf.end();

On the client side, the following code snippet was used:

function base64ToArrayBuffer(data) {
  var binaryString = window.atob(data);
  var binaryLen = binaryString.length;
  var bytes = new Uint8Array(binaryLen);
  for (var i = 0; i < binaryLen; i++) {
    var ascii = binaryString.charCodeAt(i);
    bytes[i] = ascii;
  }
  return bytes;
}

// Inside the response handler:
const arraybuffer = base64ToArrayBuffer(response);
const blob = new Blob([arraybuffer], { type: "application/pdf" });
saveAs(blob, "test.pdf");

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

<span> creating a line break after the second sentence

Link to Code: http://jsfiddle.net/MuHvy/ Javascript: $(document).ready(function () { $(".addTag").click(function () { $('.questao').html($('.questao').html() + '&nbsp;<span contentEditable="fa ...

What is the process for establishing a web service method that can be accessed via Javascript in ASP .Net (Aspx)?

Currently, I am facing an issue where I need to download a list of PDF files and then pass the names of these files as parameters to a method in the code behind. I have attempted using Page Methods and Web Methods, but encountered limitations due to their ...

Issues with layout display in separate route file

My express application utilizes handlebars as the template engine. To keep things organized, I have separated my routes into two files - index.js for localhost:3000/ and agency.js for localhost:3000/agency/. This prevents overcrowding with hundreds of line ...

Encountering a Problem with ContentEditable in AngularJS

Here is the code snippet I am working with: <!doctype html> <html ng-app="flyerGen"> <head> <script src="http://code.angularjs.org/1.0.5/angular.min.js"></script> <script> angular.module('flyerGen', []).direct ...

AJax request is failing to execute - Different page is being displayed

Today, I decided to delve into the world of AJAX and started learning the basics. I attempted to create a simple AJAX call, but instead of receiving a response asynchronously, it just loaded the PHP script page as if it was a normal form submission. html ...

My goal is to generate four HTML buttons that trigger specific functions: addition, subtraction, multiplication, and division

I am currently learning JavaScript, and I am facing some challenges with my assignment. The task is to create four buttons in HTML that trigger different functions - addition, subtraction, multiplication, and division. The goal is for the user to input two ...

Adjust the placement of the div dynamically in response to the positioning of another div tag

I have an icon that resembles a chat bubble. If the position of the icon is not fixed, how can I display the chat bubble relative to the icon and adjust its position dynamically based on the icon's location? See image here #logowrap{ padding: 8px ...

Is it possible to prevent an iFrame from loading its src until a certain function is triggered?

Currently, my webpage has multiple iFrames that are being populated with sources dynamically. However, the page's performance is suffering due to all iframes loading simultaneously. To improve this, I want to delay the loading of these iframes until a ...

Retrieve specific information by clicking a button within a table cell on the data grid in React.js

I am just starting out with React and have a query. I have set up a data table with some dummy information using a React data table. How can I make the cells of the table clickable so that when clicked, the data is displayed on a form located on the same p ...

Can we set a specific length for an array passed in as a prop?

Can we use Typescript to specify the exact length of an array coming from props? Consider the following array of objects: const sampleArray = [ { key: '1', label: 'Label 1', value: 9 }, { key: '2', label: 'Label 2&ap ...

Strange problem with Mongoose and MongoDB arises while operating MEAN application on Openshift platform

My journey with Openshift has been quite eventful. From making drastic changes to learning about version-ing and nvm (Node Version Manager), it has been a rollercoaster ride. Dealing with npm versions to ensure compatibility with the server used express ve ...

Mastering the Art of Concise Writing: Tips to

Is there a way to write more concisely, maybe even in a single line? this.xxx = smt.filter(item => item.Id === this.smtStatus.ONE); this.yyy = smt.filter(item => item.Id === this.smtStatus.TWO); this.zzz = smt.filter(item => item.Id == ...

Getting systemjs to load a module from a CDN in global format: The ultimate guide

I keep encountering the following error: EXCEPTION: ReferenceError: cast is not defined in [null] To create a custom Chromecast receiver application, you need to utilize a specific js file that exposes the necessary functionality through a global 'ca ...

Encountering a 404 error in an AngularJS app within Cordova on Android

Currently, I am working on an android application using Cordova and AngularJS (front-end framework OnsenUI). Below is the code snippet for my GET request to retrieve data from the server: $http.get(url+"getlotterylist").then(function(msg){ $scope. ...

Utilizing winston to generate multiple log files with set maximum sizes and daily rotation

Currently, I am utilizing winston for logging with a maximum size and daily rotation. I am interested in having this functionality with one file per API endpoint to define multiple log files. Is there a way to achieve this? Displayed below is my winston ...

Retrieve the element that triggered the event listener within Nuxt

I am currently developing a Nuxt project where I have set up my component using the code below. The select-parent-container has a click event attached to it. Whenever this event is triggered, I need to identify and return the specific parent container that ...

JavaScript returns an undefined value when accessing a JSON array

I'm a beginner in the world of JavaScript and I find myself stuck on an issue. I've created a backend using Java SE, Jersey, and Jackson, everything seems to be running smoothly as my REST endpoint is up and running. However, I'm facing diff ...

Retrieving intricate JSON data from a specific web address

I need assistance in extracting and printing the date value from the JSON content available at the specified URL. Specifically, I am looking to retrieve the date value of "data.content.containers.container.locationDateTime" only if the "data.content.conta ...

Issue transferring cookies from Express.js server to Next.js 14 client

My current setup is as follows: Frontend using Next.js 14 App Router with backend on Express.js Frontend runs on http://localhost:3000 and backend on http://localhost:4000 I am encountering issues sending cookies with res.cookie from my backend. Interest ...

The bootstrap carousel is unable to load at the moment

I've been attempting to create a carousel using Bootstrap, but it's not displaying correctly in Firefox or Google Chrome on Windows 8. Here's the code I used, could someone please help me identify what I might have done incorrectly? <htm ...