safeer-pdf-generator
Version:
Framework-agnostic PDF generation library with chunking, merging, S3 upload, and email delivery
441 lines (340 loc) • 10.6 kB
Markdown
# Advanced Express.js PDF Generation API
This example demonstrates how to build a comprehensive RESTful API for PDF generation using `pdf-reporter` with Express.js.
## Features
- 🚀 **RESTful API Design** - Clean, intuitive endpoints
- 📊 **Advanced PDF Generation** - Multiple templates and customization options
- ⚡ **Async Processing** - Background job processing for large datasets
- 📈 **Performance Monitoring** - Built-in metrics and estimation
- 🔒 **Rate Limiting** - Protection against abuse
- 🛡️ **Error Handling** - Comprehensive error handling and validation
- 📁 **File Operations** - PDF merging, splitting, and page extraction
- 🔍 **PDF Analysis** - Analyze PDF properties and metadata
- 📊 **Health Checks** - Service monitoring and diagnostics
## Quick Start
### Installation
```bash
cd examples/express-app
npm install
```
### Start the Server
```bash
# Development mode with auto-reload
npm run dev
# Production mode
npm start
```
The API will be available at `http://localhost:3000`
## API Endpoints
### Core Endpoints
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/` | API information and documentation |
| `GET` | `/api/health` | Detailed health check |
| `GET` | `/api/metrics` | Service metrics and statistics |
### Data Endpoints
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/samples/:type` | Get sample data (customers/sales) |
### PDF Generation
| Method | Endpoint | Description |
|--------|----------|-------------|
| `POST` | `/api/generate` | Generate PDF synchronously |
| `POST` | `/api/generate/async` | Generate PDF asynchronously |
| `POST` | `/api/estimate` | Estimate generation performance |
### PDF Operations
| Method | Endpoint | Description |
|--------|----------|-------------|
| `POST` | `/api/merge` | Merge multiple PDFs |
| `POST` | `/api/split` | Split PDF into individual pages |
| `POST` | `/api/extract` | Extract specific pages from PDF |
| `POST` | `/api/analyze` | Analyze PDF properties |
### Job Management
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/job/:id` | Get async job status |
| `GET` | `/api/job/:id/download` | Download completed PDF |
## Usage Examples
### 1. Get Sample Data
```bash
curl -X GET "http://localhost:3000/api/samples/customers?count=50"
```
### 2. Generate PDF Synchronously
```bash
curl -X POST http://localhost:3000/api/generate \\
-H "Content-Type: application/json" \\
-d '{
"title": "Customer Report",
"data": [
{
"id": 1,
"name": "John Doe",
"email": "john@example.com",
"amount": 1250.00,
"status": "Active",
"region": "North America"
}
],
"columns": [
{"key": "id", "title": "ID", "dataIndex": "id", "flex": 1},
{"key": "name", "title": "Name", "dataIndex": "name", "flex": 3},
{"key": "email", "title": "Email", "dataIndex": "email", "flex": 3},
{"key": "amount", "title": "Amount", "dataIndex": "amount", "flex": 2, "type": "currency"},
{"key": "status", "title": "Status", "dataIndex": "status", "flex": 2},
{"key": "region", "title": "Region", "dataIndex": "region", "flex": 2}
],
"options": {
"template": "modern-business",
"format": "A4",
"orientation": "portrait"
},
"userInfo": {
"companyName": "Your Company",
"name": "Your Name"
}
}' \\
--output report.pdf
```
### 3. Generate PDF Asynchronously
```bash
# Start async job
curl -X POST http://localhost:3000/api/generate/async \\
-H "Content-Type: application/json" \\
-d '{
"title": "Large Dataset Report",
"data": [...], // Large dataset
"columns": [...]
}'
# Response: {"jobId": "abc123", "status": "accepted", "checkStatusUrl": "/api/job/abc123"}
# Check job status
curl -X GET http://localhost:3000/api/job/abc123
# Download when complete
curl -X GET http://localhost:3000/api/job/abc123/download --output large-report.pdf
```
### 4. Estimate Performance
```bash
curl -X POST http://localhost:3000/api/estimate \\
-H "Content-Type: application/json" \\
-d '{
"data": [...], // Your dataset
"columns": [...], // Your columns
"options": {"template": "modern-business"}
}'
# Response includes estimated time and memory usage
```
### 5. Merge PDFs
```bash
curl -X POST http://localhost:3000/api/merge \\
-H "Content-Type: application/json" \\
-d '{
"pdfs": [
"base64-encoded-pdf-1",
"base64-encoded-pdf-2"
]
}' \\
--output merged.pdf
```
### 6. Split PDF
```bash
curl -X POST http://localhost:3000/api/split \\
-H "Content-Type: application/json" \\
-d '{
"pdf": "base64-encoded-pdf-data"
}'
# Returns array of base64-encoded pages
```
### 7. Extract Pages
```bash
curl -X POST http://localhost:3000/api/extract \\
-H "Content-Type: application/json" \\
-d '{
"pdf": "base64-encoded-pdf-data",
"pages": [1, 3, 5]
}' \\
--output extracted-pages.pdf
```
## Templates
The API includes a advanced `modern-business` template with:
- 🎨 Modern gradient design
- 📊 Automatic metrics calculation
- 📈 Status badges with color coding
- 💫 Animated background patterns
- 📱 Responsive layout
- 🏢 Company branding support
## Configuration
### Environment Variables
```env
PORT=3000
NODE_ENV=production
```
### Rate Limiting
- 100 requests per 15 minutes per IP
- Configurable in the server setup
### File Storage
The API creates these directories:
- `uploads/` - Temporary file uploads
- `output/` - Generated PDF storage
- `cache/` - Cached results
### Job Management
- Jobs are automatically cleaned up after 24 hours
- In production, consider using Redis for job storage
## Error Handling
The API provides comprehensive error responses:
```json
{
"error": "Error description",
"message": "Detailed error message",
"code": "ERROR_CODE",
"timestamp": "2024-01-01T00:00:00.000Z"
}
```
Common error codes:
- `VALIDATION_ERROR` - Invalid request data
- `PDF_GENERATION_ERROR` - PDF generation failed
- `JOB_NOT_FOUND` - Async job not found
- `RATE_LIMIT_EXCEEDED` - Too many requests
## Monitoring
### Health Check
```bash
curl -X GET http://localhost:3000/api/health
```
### Metrics
```bash
curl -X GET http://localhost:3000/api/metrics
```
Metrics include:
- Request counts and success rates
- Average processing times
- Memory usage
- Active/completed jobs
- Template usage statistics
## Production Deployment
### Docker
```dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
```
### Environment Setup
```bash
# Install dependencies
npm ci --only=production
# Set environment
export NODE_ENV=production
export PORT=3000
# Start server
npm start
```
### Scaling Considerations
- Use Redis for job storage in clustered environments
- Implement proper logging (Winston, etc.)
- Add authentication/authorization
- Set up monitoring (Prometheus, New Relic, etc.)
- Use a reverse proxy (Nginx) for SSL and load balancing
## Integration Examples
### Frontend Integration (JavaScript)
```javascript
class PDFGeneratorClient {
constructor(baseUrl = 'http://localhost:3000') {
this.baseUrl = baseUrl;
}
async generatePDF(data) {
const response = await fetch(\`\${this.baseUrl}/api/generate\`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
if (!response.ok) {
throw new Error(\`PDF generation failed: \${response.statusText}\`);
}
return response.blob();
}
async generateAsync(data) {
const response = await fetch(\`\${this.baseUrl}/api/generate/async\`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
const job = await response.json();
return this.pollJob(job.jobId);
}
async pollJob(jobId, interval = 2000) {
while (true) {
const response = await fetch(\`\${this.baseUrl}/api/job/\${jobId}\`);
const job = await response.json();
if (job.status === 'completed') {
const pdfResponse = await fetch(\`\${this.baseUrl}/api/job/\${jobId}/download\`);
return pdfResponse.blob();
} else if (job.status === 'failed') {
throw new Error(\`Job failed: \${job.error}\`);
}
await new Promise(resolve => setTimeout(resolve, interval));
}
}
}
// Usage
const client = new PDFGeneratorClient();
const pdfBlob = await client.generatePDF({
title: "My Report",
data: [...],
columns: [...]
});
```
### Python Integration
```python
import requests
import time
import json
class PDFGeneratorClient:
def __init__(self, base_url="http://localhost:3000"):
self.base_url = base_url
def generate_pdf(self, data):
response = requests.post(
f"{self.base_url}/api/generate",
json=data,
headers={"Content-Type": "application/json"}
)
response.raise_for_status()
return response.content
def generate_async(self, data):
response = requests.post(
f"{self.base_url}/api/generate/async",
json=data
)
job = response.json()
return self.poll_job(job["jobId"])
def poll_job(self, job_id, interval=2):
while True:
response = requests.get(f"{self.base_url}/api/job/{job_id}")
job = response.json()
if job["status"] == "completed":
pdf_response = requests.get(f"{self.base_url}/api/job/{job_id}/download")
return pdf_response.content
elif job["status"] == "failed":
raise Exception(f"Job failed: {job['error']}")
time.sleep(interval)
# Usage
client = PDFGeneratorClient()
pdf_data = client.generate_pdf({
"title": "My Report",
"data": [...],
"columns": [...]
})
with open("report.pdf", "wb") as f:
f.write(pdf_data)
```
## Contributing
1. Fork the repository
2. Create your feature branch
3. Make your changes
4. Add tests if applicable
5. Submit a pull request
## License
MIT License - see the [LICENSE](../../LICENSE) file for details.
## Support
- 📚 [Documentation](https://github.com/Safeersoft/pdf-reporter)
- 🐛 [Issue Tracker](https://github.com/Safeersoft/pdf-reporter/issues)
- 📧 [Email Support](mailto:support.com)