- ExitCodeZer0
- Posts
- Convert HTML to PDF with Node.js: A Complete Guide to Using the FileSlap API
Convert HTML to PDF with Node.js: A Complete Guide to Using the FileSlap API
Transform your HTML content into professional PDFs using Node.js and our lightning-fast API
Why Convert HTML to PDF with Node.js?
Node.js developers often need to generate PDFs from HTML content for:
Invoice generation - Create professional invoices for e-commerce
Report creation - Convert data dashboards to printable formats
Document processing - Generate PDFs from user-submitted content
Email attachments - Send formatted documents via email services
Content archiving - Convert blog posts and articles to PDF
While there are local Node.js libraries like puppeteer
or wkhtmltopdf
, they come with installation headaches, dependency issues, and inconsistent rendering across different systems. That's where the FileSlap API comes in - a cloud-based solution that handles all the complexity for you.
Getting Started with FileSlap API
1. Get Your API Key
First, sign up at fileslap.com and grab your API key. It's free to start with 50 conversions per month.
2. Install Required Dependencies
npm install node-fetch
That's it! No complex PDF libraries or system dependencies to worry about.
Basic HTML to PDF Conversion
Here's the simplest way to convert HTML to PDF:
import fetch from "node-fetch";
import fs from "fs";
async function convertHtmlToPdf(htmlContent, apiKey) {
const url = "https://api.fileslap.com/api/convert";
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-KEY": apiKey
},
body: JSON.stringify({ html: htmlContent })
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP ${response.status}: ${errorText}`);
}
// Save the PDF
const buffer = await response.arrayBuffer();
fs.writeFileSync("output.pdf", Buffer.from(buffer));
console.log("PDF created successfully!");
}
// Example usage
const htmlContent = `
<!DOCTYPE html>
<html>
<head>
<title>Sample Document</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
h1 { color: #333; }
</style>
</head>
<body>
<h1>Hello from Node.js!</h1>
<p>This HTML was converted to PDF using the FileSlap API.</p>
</body>
</html>
`;
const apiKey = "your_api_key_here";
convertHtmlToPdf(htmlContent, apiKey);
Using Native Fetch (Node.js 18+)
If you're using Node.js 18 or later, you can use the built-in fetch:
import fs from "fs";
async function convertHtmlToPdf(htmlContent, apiKey) {
const response = await fetch("https://api.fileslap.com/api/convert", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-KEY": apiKey
},
body: JSON.stringify({ html: htmlContent })
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP ${response.status}: ${errorText}`);
}
const buffer = await response.arrayBuffer();
fs.writeFileSync("output.pdf", Buffer.from(buffer));
console.log("PDF created successfully!");
}
Real-World Examples
1. Invoice Generator
import fetch from "node-fetch";
import fs from "fs";
async function generateInvoice(orderData, apiKey) {
const html = `
<!DOCTYPE html>
<html>
<head>
<title>Invoice #${orderData.orderNumber}</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
.header { text-align: center; border-bottom: 2px solid #333; padding-bottom: 20px; }
.invoice-details { margin: 30px 0; }
.items-table { width: 100%; border-collapse: collapse; margin: 20px 0; }
.items-table th, .items-table td { border: 1px solid #ddd; padding: 8px; text-align: left; }
.total { font-weight: bold; font-size: 18px; text-align: right; }
</style>
</head>
<body>
<div class="header">
<h1>INVOICE</h1>
<p>Order #${orderData.orderNumber} | Date: ${orderData.orderDate}</p>
</div>
<div class="invoice-details">
<h3>Bill To:</h3>
<p>${orderData.customerName}<br>
${orderData.customerEmail}<br>
${orderData.customerAddress}</p>
</div>
<table class="items-table">
<thead>
<tr>
<th>Item</th>
<th>Quantity</th>
<th>Price</th>
<th>Total</th>
</tr>
</thead>
<tbody>
${orderData.items.map(item => `
<tr>
<td>${item.name}</td>
<td>${item.quantity}</td>
<td>$${item.price}</td>
<td>$${item.quantity * item.price}</td>
</tr>
`).join('')}
</tbody>
</table>
<div class="total">
<p>Total: $${orderData.total}</p>
</div>
</body>
</html>
`;
const response = await fetch("https://api.fileslap.com/api/convert", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-KEY": apiKey
},
body: JSON.stringify({ html })
});
if (!response.ok) {
throw new Error(`PDF generation failed: ${response.status}`);
}
const buffer = await response.arrayBuffer();
const filename = `invoice-${orderData.orderNumber}.pdf`;
fs.writeFileSync(filename, Buffer.from(buffer));
return filename;
}
// Usage
const orderData = {
orderNumber: "ORD-12345",
orderDate: new Date().toLocaleDateString(),
customerName: "John Doe",
customerEmail: "[email protected]",
customerAddress: "123 Main St, City, State 12345",
items: [
{ name: "Web Development", quantity: 1, price: 1500 },
{ name: "Hosting Setup", quantity: 1, price: 200 }
],
total: 1700
};
generateInvoice(orderData, "your_api_key");
2. Report Generator with Charts
async function generateReport(data, apiKey) {
// Create a simple chart using HTML/CSS
const chartHtml = data.map(item => {
const percentage = (item.value / Math.max(...data.map(d => d.value))) * 100;
return `
<div style="margin: 10px 0;">
<div style="display: flex; justify-content: space-between;">
<span>${item.label}</span>
<span>${item.value}</span>
</div>
<div style="background: #f0f0f0; height: 20px; border-radius: 10px;">
<div style="background: #007bff; height: 100%; width: ${percentage}%; border-radius: 10px;"></div>
</div>
</div>
`;
}).join('');
const html = `
<!DOCTYPE html>
<html>
<head>
<title>Monthly Report</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
.header { text-align: center; margin-bottom: 30px; }
.chart { margin: 20px 0; }
</style>
</head>
<body>
<div class="header">
<h1>Monthly Sales Report</h1>
<p>Generated on ${new Date().toLocaleDateString()}</p>
</div>
<div class="chart">
<h2>Sales Performance</h2>
${chartHtml}
</div>
</body>
</html>
`;
const response = await fetch("https://api.fileslap.com/api/convert", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-KEY": apiKey
},
body: JSON.stringify({ html })
});
if (!response.ok) {
throw new Error(`PDF generation failed: ${response.status}`);
}
const buffer = await response.arrayBuffer();
fs.writeFileSync("report.pdf", Buffer.from(buffer));
console.log("Report generated successfully!");
}
// Usage
const reportData = [
{ label: "Product A", value: 1500 },
{ label: "Product B", value: 2200 },
{ label: "Product C", value: 800 }
];
generateReport(reportData, "your_api_key");
Error Handling and Best Practices
Robust Error Handling
async function convertWithRetry(htmlContent, apiKey, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await fetch("https://api.fileslap.com/api/convert", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-KEY": apiKey
},
body: JSON.stringify({ html: htmlContent })
});
if (response.ok) {
return await response.arrayBuffer();
}
if (response.status === 429) {
const waitTime = Math.pow(2, attempt) * 1000;
console.log(`Rate limited. Waiting ${waitTime}ms...`);
await new Promise(resolve => setTimeout(resolve, waitTime));
continue;
}
const errorText = await response.text();
throw new Error(`HTTP ${response.status}: ${errorText}`);
} catch (error) {
if (attempt === maxRetries) {
throw error;
}
console.log(`Attempt ${attempt} failed:`, error.message);
}
}
}
Validate HTML Content
function validateHtml(htmlContent) {
// Basic HTML validation
const requiredTags = ['<html>', '<head>', '<body>'];
const htmlLower = htmlContent.toLowerCase();
for (const tag of requiredTags) {
if (!htmlLower.includes(tag)) {
return false;
}
}
return true;
}
async function safeConvert(htmlContent, apiKey) {
if (!validateHtml(htmlContent)) {
throw new Error("Invalid HTML content");
}
return await convertWithRetry(htmlContent, apiKey);
}
Integration with Popular Frameworks
Express.js Integration
import express from "express";
import fetch from "node-fetch";
const app = express();
app.use(express.json());
app.post('/generate-pdf', async (req, res) => {
try {
const { html } = req.body;
const apiKey = process.env.FILESLAP_API_KEY;
const response = await fetch("https://api.fileslap.com/api/convert", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-KEY": apiKey
},
body: JSON.stringify({ html })
});
if (!response.ok) {
const errorText = await response.text();
return res.status(400).json({ error: `PDF generation failed: ${errorText}` });
}
const pdfBuffer = await response.arrayBuffer();
res.setHeader('Content-Type', 'application/pdf');
res.setHeader('Content-Disposition', 'attachment; filename="generated.pdf"');
res.send(Buffer.from(pdfBuffer));
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Next.js API Route
// pages/api/generate-pdf.js
export default async function handler(req, res) {
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}
try {
const { html } = req.body;
const apiKey = process.env.FILESLAP_API_KEY;
const response = await fetch("https://api.fileslap.com/api/convert", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-KEY": apiKey
},
body: JSON.stringify({ html })
});
if (!response.ok) {
const errorText = await response.text();
return res.status(400).json({ error: `PDF generation failed: ${errorText}` });
}
const pdfBuffer = await response.arrayBuffer();
res.setHeader('Content-Type', 'application/pdf');
res.setHeader('Content-Disposition', 'attachment; filename="generated.pdf"');
res.send(Buffer.from(pdfBuffer));
} catch (error) {
res.status(500).json({ error: error.message });
}
}
Serverless Function (Vercel/Netlify)
// api/generate-pdf.js
export default async function handler(req, res) {
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}
try {
const { html } = req.body;
const apiKey = process.env.FILESLAP_API_KEY;
const response = await fetch("https://api.fileslap.com/api/convert", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-KEY": apiKey
},
body: JSON.stringify({ html })
});
if (!response.ok) {
const errorText = await response.text();
return res.status(400).json({ error: `PDF generation failed: ${errorText}` });
}
const pdfBuffer = await response.arrayBuffer();
res.setHeader('Content-Type', 'application/pdf');
res.setHeader('Content-Disposition', 'attachment; filename="generated.pdf"');
res.send(Buffer.from(pdfBuffer));
} catch (error) {
res.status(500).json({ error: error.message });
}
}
Performance Tips
1. Batch Processing
async function batchConvert(htmlTemplates, apiKey) {
const promises = htmlTemplates.map(async (template, index) => {
try {
const response = await fetch("https://api.fileslap.com/api/convert", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-KEY": apiKey
},
body: JSON.stringify({ html: template })
});
if (!response.ok) {
throw new Error(`Failed to convert template ${index}`);
}
return await response.arrayBuffer();
} catch (error) {
console.error(`Error converting template ${index}:`, error);
return null;
}
});
return await Promise.all(promises);
}
2. Caching Strategies
import crypto from "crypto";
const cache = new Map();
function getCacheKey(htmlContent) {
return crypto.createHash('md5').update(htmlContent).digest('hex');
}
async function convertWithCache(htmlContent, apiKey) {
const cacheKey = getCacheKey(htmlContent);
if (cache.has(cacheKey)) {
console.log('Using cached PDF');
return cache.get(cacheKey);
}
const pdfBuffer = await convertWithRetry(htmlContent, apiKey);
cache.set(cacheKey, pdfBuffer);
return pdfBuffer;
}
3. Stream Processing
import { Readable } from "stream";
async function streamPdf(htmlContent, apiKey, res) {
const response = await fetch("https://api.fileslap.com/api/convert", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-KEY": apiKey
},
body: JSON.stringify({ html: htmlContent })
});
if (!response.ok) {
throw new Error(`PDF generation failed: ${response.status}`);
}
const pdfBuffer = await response.arrayBuffer();
const stream = Readable.from(Buffer.from(pdfBuffer));
res.setHeader('Content-Type', 'application/pdf');
res.setHeader('Content-Disposition', 'attachment; filename="generated.pdf"');
stream.pipe(res);
}
Environment Variables
Store your API key securely using environment variables:
# .env
FILESLAP_API_KEY=your_api_key_here
import dotenv from "dotenv";
dotenv.config();
const apiKey = process.env.FILESLAP_API_KEY;
Error Codes and Handling
The FileSlap API returns standard HTTP status codes:
200: PDF generated successfully
400: Bad request - invalid HTML or missing fields
401: Unauthorized - invalid or missing API key
429: Rate limit exceeded or quota exceeded
500: Internal server error
async function handleApiResponse(response) {
switch (response.status) {
case 200:
return await response.arrayBuffer();
case 400:
const error400 = await response.text();
throw new Error(`Invalid request: ${error400}`);
case 401:
throw new Error('Invalid API key. Please check your credentials.');
case 429:
throw new Error('Rate limit exceeded. Please try again later.');
case 500:
throw new Error('Service temporarily unavailable. Please try again.');
default:
throw new Error(`Unexpected error: ${response.status}`);
}
}
Get Started Today
Ready to simplify your PDF generation?
Sign up at fileslap.com
Get your API key from the dashboard
Install node-fetch (or use native fetch in Node.js 18+)
Start converting HTML to PDF with just a few lines of code
No more wrestling with local PDF libraries or dealing with system dependencies. The FileSlap API handles all the complexity while you focus on building great applications.
Need Help?
Documentation: fileslap.com/docs
API Reference: Complete API documentation with examples
Support: Reach out to our team for custom integration help
Transform your HTML content into professional PDFs with the power of Node.js and FileSlap's cloud-based API.
Tags: #NodeJS #PDF #API #HTML #JavaScript #WebDevelopment #FileSlap #Backend