Skip to content
This repository was archived by the owner on Jul 27, 2024. It is now read-only.

Commit 95c80d7

Browse files
committed
Added node-based file attachment upload example
1 parent f165f61 commit 95c80d7

File tree

4 files changed

+289
-0
lines changed

4 files changed

+289
-0
lines changed

Diff for: node-upload-attachment/index.js

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Libraries used
2+
const fs = require('fs');
3+
const path = require('path');
4+
const axios = require('axios');
5+
const FormData = require('form-data');
6+
7+
// BookStack API variables
8+
// Uses values on the environment unless hardcoded
9+
// To hardcode, add values to the empty strings in the below.
10+
const bookStackConfig = {
11+
base_url: '' || process.env.BS_URL,
12+
token_id: '' || process.env.BS_TOKEN_ID,
13+
token_secret: '' || process.env.BS_TOKEN_SECRET,
14+
};
15+
16+
// Script Logic
17+
////////////////
18+
19+
// Check arguments provided
20+
if (process.argv.length < 4) {
21+
console.error('Both <page_id> and <file_path> arguments need to be provided');
22+
return;
23+
}
24+
25+
// Get arguments passed via command
26+
const [_exec, _script, pageId, filePath] = process.argv;
27+
28+
// Check the given file exists
29+
if (!fs.existsSync(filePath)) {
30+
console.error(`File at "${filePath}" could not be found`);
31+
return;
32+
}
33+
34+
// Get the file name and create a read stream from the given file
35+
const fileStream = fs.createReadStream(filePath);
36+
const fileName = path.basename(filePath);
37+
38+
// Gather our form data with all the required bits
39+
const formPostData = new FormData();
40+
formPostData.append('file', fileStream);
41+
formPostData.append('name', fileName);
42+
formPostData.append('uploaded_to', pageId);
43+
44+
// Create an axios instance for our API
45+
const api = axios.create({
46+
baseURL: bookStackConfig.base_url.replace(/\/$/, '') + '/api/',
47+
timeout: 30000,
48+
headers: { 'Authorization' : `Token ${bookStackConfig.token_id}:${bookStackConfig.token_secret}` },
49+
});
50+
51+
// Wrap the rest of our code in an async function, so we can await within.
52+
(async function() {
53+
54+
// Upload the file using the gathered data
55+
// Sends it with a "Content-Type: multipart/form-data" with the post
56+
// body formatted as multipart/form-data content, with the "FormData" object
57+
// from the "form-data" library does for us.
58+
const {data: attachment} = await api.post('/attachments', formPostData, {
59+
headers: formPostData.getHeaders(),
60+
});
61+
62+
// Output the results
63+
console.info(`File successfully uploaded to page ${pageId}.`);
64+
console.info(` - Attachment ID: ${attachment.id}`);
65+
console.info(` - Attachment Name: ${attachment.name}`);
66+
67+
})().catch(err => {
68+
// Handle API errors
69+
if (err.response) {
70+
console.error(`Request failed with status ${err.response.status} [${err.response.statusText}]`);
71+
console.error(JSON.stringify(err.response.data));
72+
return;
73+
}
74+
// Output all other errors
75+
console.error(err)
76+
});

Diff for: node-upload-attachment/package-lock.json

+156
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: node-upload-attachment/package.json

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "upload-attachment",
3+
"version": "1.0.0",
4+
"description": "This script will upload the passed file into a BookStack book via the API.",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"keywords": [],
10+
"author": "Dan Brown",
11+
"license": "MIT",
12+
"dependencies": {
13+
"axios": "^0.25.0",
14+
"form-data": "^4.0.0"
15+
}
16+
}

Diff for: node-upload-attachment/readme.md

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Upload a file attachment to a BookStack page
2+
3+
This script will take a path to any local file and attempt
4+
to upload it to a BookStack page as an attachment
5+
using the API using a multipart/form-data request.
6+
7+
This is a simplistic example of a NodeJS script. You will likely want to
8+
alter and extend this script to suit your use-case.
9+
10+
## Requirements
11+
12+
You will need NodeJS installed (Tested on v16, may work on earlier versions).
13+
14+
## Running
15+
16+
First, download all the files in the same directory as this readme to a folder on your system
17+
and run the below from within that directory.
18+
19+
```bash
20+
# Install NodeJS dependencies via NPM
21+
npm install
22+
23+
# Setup
24+
# ALTERNATIVELY: Open the script and add to the empty strings in the variables at the top.
25+
export BS_URL=https://bookstack.example.com # Set to be your BookStack base URL
26+
export BS_TOKEN_ID=abc123 # Set to be your API token_id
27+
export BS_TOKEN_SECRET=123abc # Set to be your API token_secret
28+
29+
# Running the script
30+
node index.js <page_id> <file_path>
31+
```
32+
33+
- `<page_id>` - The ID of the page you want to upload the attachment to.
34+
- `<file_path>` - File you want to upload as an attachment.
35+
36+
## Examples
37+
38+
```bash
39+
# Upload the 'cat-image-collection.zip' file as an attachment to page of ID 205
40+
node index.js 205 ./cat-image-collection.zip
41+
```

0 commit comments

Comments
 (0)