Last active
April 10, 2024 19:23
-
-
Save castodius/84c5ec49cceca5eb9a667dec3058364e to your computer and use it in GitHub Desktop.
Exporting Confluence page as PDF using NodeJS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { writeFileSync } from 'fs' | |
/** | |
* Example of how to export a Confluence Page as a PDF and writing it to disk | |
* The code has poor error handling, but is hopefully easy to understand | |
* | |
* The basic steps are: | |
* - Load PDF export page | |
* - Find task id | |
* - Wait for task to complete and get result path in return | |
* - Get task result which is a signed AWS S3 url allowing you to download the PDF | |
* - Call the S3 url and do whatever you want with the returned value | |
* | |
* Logic was extracted from https://github.com/atlassian-api/atlassian-python-api/blob/master/atlassian/confluence.py | |
*/ | |
const confluenceDomain = '' | |
const username = '' | |
// password probably works as well | |
const apiToken = '' | |
// id of page you want to export as PDF, found in the url of the page itself. Always 10 digits from what I can tell | |
const pageId = '' | |
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)) | |
const waitForTaskCompletion = async (taskId) => { | |
while (true) { | |
await sleep(2000) | |
const progress = await fetch(`${apiDomain}/wiki/services/api/v1/task/${taskId}/progress`, { headers }) | |
.then(res => res.json()) | |
console.log(progress) | |
switch (progress.state) { | |
case 'PDF_GENERATED': | |
case 'IN_PROGRESS': | |
break | |
case 'UPLOADED_TO_S3': | |
return progress.result | |
default: | |
throw new Error('Unknown state') | |
} | |
} | |
} | |
const apiDomain = `https://${confluenceDomain}.atlassian.net` | |
const headers = new Headers() | |
headers.append('Authorization', `Basic ${Buffer.from(username + ':' + apiToken).toString('base64')})}`) | |
headers.append('X-Atlassian-Token', 'no-check') | |
// This serves two purposes. It triggers the PDF generation and returns the HTML page which contains the task id | |
const pdfDownloadPage = await fetch(`${apiDomain}/wiki/spaces/flyingpdf/pdfpageexport.action?pageId=${pageId}`, { headers }) | |
.then(res => res.text()) | |
// The line we are looking for is of format " <meta name="ajs-taskId" content="54b4d158-2a34-4bf4-acc1-58da7f27b3dd">" | |
const taskId = pdfDownloadPage | |
.split('\n') | |
.find(line => line.includes('ajs-taskId')) | |
.match(/[a-f0-9]{8}-[a-f0-9-]+/)[0] | |
const taskResult = await waitForTaskCompletion(taskId) | |
const downloadUrl = await fetch(`${apiDomain}${taskResult}`, { headers }) | |
.then(res => res.text()) | |
const pdfBuffer = await fetch(downloadUrl) | |
.then(res => res.arrayBuffer()) | |
writeFileSync('./page.pdf', Buffer.from(pdfBuffer)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment