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

Commit 482b772

Browse files
committed
Added python attachment upload example
1 parent ed1748f commit 482b772

File tree

4 files changed

+138
-1
lines changed

4 files changed

+138
-1
lines changed

Diff for: .gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
.idea/
2-
node_modules/
2+
node_modules/
3+
venv/

Diff for: python-upload-attachment/main.py

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import os
2+
import sys
3+
import requests
4+
5+
# This is where BookStack API details can be hard-coded if you prefer
6+
# to write them in this script instead of using environment variables.
7+
default_bookstack_options = {
8+
"url": "",
9+
"token_id": "",
10+
"token_secret": "",
11+
}
12+
13+
14+
# Gather the BookStack API options either from the hard-coded details above otherwise
15+
# it defaults back to environment variables.
16+
def gather_api_options() -> dict:
17+
return {
18+
"url": default_bookstack_options["url"] or os.getenv("BS_URL"),
19+
"token_id": default_bookstack_options["token_id"] or os.getenv("BS_TOKEN_ID"),
20+
"token_secret": default_bookstack_options["token_secret"] or os.getenv("BS_TOKEN_SECRET"),
21+
}
22+
23+
24+
# Send a multipart post request to BookStack, at the given endpoint with the given data.
25+
def bookstack_post_multipart(endpoint: str, data: dict) -> dict:
26+
# Fetch the API-specific options
27+
bs_api_opts = gather_api_options()
28+
29+
# Format the request URL and the authorization header, so we can access the API
30+
request_url = bs_api_opts["url"].rstrip("/") + "/api/" + endpoint.lstrip("/")
31+
request_headers = {
32+
"Authorization": "Token {}:{}".format(bs_api_opts["token_id"], bs_api_opts["token_secret"])
33+
}
34+
35+
# Make the request to bookstack with the gathered details
36+
response = requests.post(request_url, headers=request_headers, files=data)
37+
38+
# Throw an error if the request was not successful
39+
response.raise_for_status()
40+
41+
# Return the response data decoded from it's JSON format
42+
return response.json()
43+
44+
45+
# Error out and exit the app
46+
def error_out(message: str):
47+
print(message)
48+
exit(1)
49+
50+
51+
# Run this when called on command line
52+
if __name__ == '__main__':
53+
54+
# Check arguments provided
55+
if len(sys.argv) < 3:
56+
error_out("Both <page_id> and <file_path> arguments need to be provided")
57+
58+
# Gather details from the command line arguments and create a file name
59+
# from the file path
60+
page_id = sys.argv[1]
61+
file_path = sys.argv[2]
62+
file_name = os.path.basename(file_path)
63+
64+
# Ensure the file exists
65+
if not os.path.isfile(file_path):
66+
error_out("Could not find provided file: {}".format(file_path))
67+
68+
# Gather the data we'll be sending to BookStack.
69+
# The format matches that what the "requests" library expects
70+
# to be provided for its "files" parameter.
71+
post_data = {
72+
"file": open(file_path, "rb"),
73+
"name": (None, file_name),
74+
"uploaded_to": (None, page_id)
75+
}
76+
77+
# Send the upload request and get back the attachment data
78+
try:
79+
attachment = bookstack_post_multipart("/attachments", post_data)
80+
except requests.HTTPError as e:
81+
error_out("Upload failed with status {} and data: {}".format(e.response.status_code, e.response.text))
82+
83+
# Output the results
84+
print("File successfully uploaded to page {}.".format(page_id))
85+
print(" - Attachment ID: {}".format(attachment['id']))
86+
print(" - Attachment Name: {}".format(attachment['name']))

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

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
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 Python script. You will likely want to
8+
alter and extend this script to suit your use-case.
9+
10+
This was written without in-depth knowledge of Python nor experience
11+
of Python common conventions, so the style and approaches may appear unconventional.
12+
13+
## Requirements
14+
15+
You will need Python 3 installed (3.10.7).
16+
This also uses pip to import requests as a dependency.
17+
18+
## Running
19+
20+
First, download all the files in the same directory as this readme to a folder on your system
21+
and run the below from within that directory.
22+
23+
```bash
24+
# Install dependencies via PIP
25+
pip install -r requirements.txt
26+
27+
# Setup
28+
# ALTERNATIVELY: Open the script and add to the empty strings in the variables at the top.
29+
export BS_URL=https://bookstack.example.com # Set to be your BookStack base URL
30+
export BS_TOKEN_ID=abc123 # Set to be your API token_id
31+
export BS_TOKEN_SECRET=123abc # Set to be your API token_secret
32+
33+
# Running the script
34+
python main.py <page_id> <file_path>
35+
```
36+
37+
- `<page_id>` - The ID of the page you want to upload the attachment to.
38+
- `<file_path>` - File you want to upload as an attachment.
39+
40+
## Examples
41+
42+
```bash
43+
# Upload the 'cat-image-collection.zip' file as an attachment to page of ID 205
44+
python main.py 205 ./cat-image-collection.zip
45+
```

Diff for: python-upload-attachment/requirements.txt

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
certifi==2022.9.24
2+
charset-normalizer==2.1.1
3+
idna==3.4
4+
requests==2.28.1
5+
urllib3==1.26.13

0 commit comments

Comments
 (0)