Skip to content

Commit 3dfd745

Browse files
committed
Add URL to PDF example
1 parent d27f736 commit 3dfd745

File tree

6 files changed

+524
-0
lines changed

6 files changed

+524
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ All examples contain a README with instructions on how to build and run them.
99
### Node.js
1010

1111
1. [Google Slides Scrolling Screenshots](./nodejs/google-slides-scrolling-screenshots) is a simple application that uses ScreenshotOne API to render scrolling screenshots of Google Slides presentations.
12+
2. [URL to PDF](./nodejs/url-to-pdf) is a simple application that uses ScreenshotOne API to render a URL as PDF.
1213

1314
### Python
1415

nodejs/url-to-pdf/.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.env
2+
node_modules/
3+
*.pdf

nodejs/url-to-pdf/README.md

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# URL to PDF Converter
2+
3+
A simple Node.js program to render a URL as PDF using [the ScreenshotOne API](https://screenshotone.com/).
4+
5+
## Prerequisites
6+
7+
- Node.js
8+
- npm
9+
- [ScreenshotOne API](https://screenshotone.com/) access key
10+
11+
## Installation
12+
13+
1. Clone this repository or download the source code.
14+
15+
```bash
16+
git clone https://github.com/screenshotone/examples.git
17+
```
18+
19+
2. Navigate to the project directory.
20+
21+
```bash
22+
cd examples/nodejs/url-to-pdf
23+
```
24+
25+
3. Install the dependencies:
26+
27+
```bash
28+
npm install
29+
```
30+
31+
4. Create a `.env` file in the project root directory and add your ScreenshotOne API access key:
32+
33+
```
34+
SCREENSHOTONE_ACCESS_KEY=your_access_key
35+
```
36+
37+
You can get your API access key by signing up at [ScreenshotOne](https://screenshotone.com/).
38+
39+
## Usage
40+
41+
### Basic Usage
42+
43+
Run the program with a URL to convert it to PDF:
44+
45+
```bash
46+
node index.js https://example.com
47+
```
48+
49+
This will generate a PDF file named `output.pdf` in the project directory.
50+
51+
### Custom Output Path
52+
53+
You can specify a custom output path for the PDF file:
54+
55+
```bash
56+
node index.js https://example.com /path/to/output.pdf
57+
```
58+
59+
### Retry Mechanism
60+
61+
The application includes a built-in retry mechanism that will automatically retry failed requests up to 3 times with an exponential backoff delay between retries. This helps handle temporary network issues or API rate limits.
62+
63+
You can modify the retry parameters in the `main()` function in `index.js`:
64+
65+
```javascript
66+
const maxRetries = 3; // Maximum number of retry attempts
67+
const retryDelay = 2000; // Initial delay between retries in milliseconds
68+
```
69+
70+
### Advanced Options
71+
72+
You can modify the `options` object in the `main()` function in `index.js` to customize the PDF generation. For a complete list of options, refer to the [ScreenshotOne API documentation](https://screenshotone.com/docs/options/).

nodejs/url-to-pdf/index.js

+144
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
const axios = require("axios");
2+
const fs = require("fs");
3+
const path = require("path");
4+
require("dotenv").config();
5+
6+
// ScreenshotOne API credentials
7+
const accessKey = process.env.SCREENSHOTONE_ACCESS_KEY;
8+
9+
if (!accessKey) {
10+
console.error(
11+
"Error: ScreenshotOne API access key is missing. Please check your .env file."
12+
);
13+
process.exit(1);
14+
}
15+
16+
// Sleep function for retries
17+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
18+
19+
// Function to convert URL to PDF with retries
20+
async function urlToPdf(
21+
url,
22+
outputPath,
23+
options = {},
24+
maxRetries = 3,
25+
retryDelay = 2000
26+
) {
27+
let retries = 0;
28+
29+
while (retries <= maxRetries) {
30+
try {
31+
// Default options for PDF generation
32+
const defaultOptions = {
33+
url,
34+
access_key: accessKey,
35+
format: "pdf",
36+
pdf_fit_one_page: "true",
37+
full_page: "true",
38+
wait_until: "networkidle0",
39+
pdf_print_background: "true",
40+
};
41+
42+
// Merge default options with custom options
43+
const mergedOptions = { ...defaultOptions, ...options };
44+
45+
// Build query string
46+
const queryString = new URLSearchParams(mergedOptions).toString();
47+
48+
// ScreenshotOne API endpoint
49+
const apiUrl = `https://api.screenshotone.com/take?${queryString}`;
50+
51+
console.log(
52+
`Generating PDF for ${url}... (Attempt ${retries + 1}/${
53+
maxRetries + 1
54+
})`
55+
);
56+
57+
// Make request to ScreenshotOne API
58+
const response = await axios({
59+
method: "get",
60+
url: apiUrl,
61+
responseType: "stream",
62+
timeout: 30000, // 30 seconds timeout
63+
});
64+
65+
// Create write stream for output file
66+
const writer = fs.createWriteStream(outputPath);
67+
68+
// Pipe response data to file
69+
response.data.pipe(writer);
70+
71+
return new Promise((resolve, reject) => {
72+
writer.on("finish", () => {
73+
console.log(`PDF saved to ${outputPath}`);
74+
resolve(outputPath);
75+
});
76+
writer.on("error", reject);
77+
});
78+
} catch (error) {
79+
retries++;
80+
81+
if (retries > maxRetries) {
82+
console.error(
83+
`Error generating PDF after ${maxRetries + 1} attempts:`,
84+
error.message
85+
);
86+
if (error.response) {
87+
console.error(
88+
"API response status:",
89+
error.response.status
90+
);
91+
}
92+
throw new Error(
93+
`Failed to generate PDF after ${maxRetries + 1} attempts: ${
94+
error.message
95+
}`
96+
);
97+
}
98+
99+
console.warn(
100+
`Attempt ${retries}/${
101+
maxRetries + 1
102+
} failed. Retrying in ${retryDelay}ms...`
103+
);
104+
console.error("Error:", error.message);
105+
106+
// Wait before retrying
107+
await sleep(retryDelay);
108+
109+
// Increase retry delay for next attempt (exponential backoff)
110+
retryDelay *= 1.5;
111+
}
112+
}
113+
}
114+
115+
// Example usage
116+
async function main() {
117+
const url = process.argv[2] || "https://www.example.com";
118+
const outputPath = process.argv[3] || path.join(__dirname, "output.pdf");
119+
120+
try {
121+
// Additional options (optional)
122+
const options = {
123+
// Add any custom options here
124+
// delay: 2000,
125+
// device_scale_factor: 1,
126+
// block_ads: 'true',
127+
// pdf_print_background: 'true',
128+
// pdf_fit_one_page: 'true',
129+
};
130+
131+
// Set retry parameters
132+
const maxRetries = 3; // Maximum number of retry attempts
133+
const retryDelay = 2000; // Initial delay between retries in milliseconds
134+
135+
await urlToPdf(url, outputPath, options, maxRetries, retryDelay);
136+
console.log("PDF generation completed successfully!");
137+
} catch (error) {
138+
console.error("PDF generation failed:", error.message);
139+
process.exit(1);
140+
}
141+
}
142+
143+
// Run the main function
144+
main();

0 commit comments

Comments
 (0)