Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#FROM node:24-alpine
FROM ghcr.io/puppeteer/puppeteer:latest

# Set environment variables for Chromium
ENV XDG_CONFIG_HOME=/tmp/.chromium
ENV XDG_CACHE_HOME=/tmp/.chromium

WORKDIR /app

COPY package.json ./
RUN npm install

COPY export.js .

EXPOSE 8000

CMD ["npm", "start"]
29 changes: 29 additions & 0 deletions Dockerfile.windows
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
FROM mcr.microsoft.com/windows/server:ltsc2022

# Download and install Node.js
RUN powershell -Command \
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12; \
Invoke-WebRequest -Uri 'https://nodejs.org/dist/v24.11.1/node-v24.11.1-x64.msi' -OutFile 'node-installer.msi'; \
Start-Process msiexec.exe -ArgumentList '/i', 'node-installer.msi', '/quiet', '/norestart' -NoNewWindow -Wait; \
Remove-Item 'node-installer.msi'

# Set working directory
WORKDIR /app

# Copy package files
COPY package.json ./

# Install npm dependencies (including Puppeteer)
RUN npm install

# Install Puppeteer browser using npx
RUN npx puppeteer browsers install chrome --install-deps

# Copy application file
COPY export.js .

# Expose port
EXPOSE 8000

# Run the application
CMD ["node", "export.js"]
114 changes: 76 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,49 +1,80 @@
# draw-image-export2

The current server-side PNG/PDF export implementation using Node, Puppeteer and Chrome headless

## Running the service (this is your instructions, not the next section)
* npm install
* npm start

- npm install
- npm start

Then add export=http://localhost:8000 (hostname and port as needed) as an URL parameter to use that service
for development and testing.

### Docker

- Run `docker build -t draw-image-export .` to build the image
- Run `docker run -it -rm -p 8000:8000 draw-image-export` to start the container and test locally.

This will run the pupeteer container on Linux. However, because Linux is missing a lot of fonts, the rendered images may not look as expected. To run the container on Windows as a Windows container with better font support, use the `Dockerfile.windows` file:

- Run `docker build -f Dockerfile.windows -t draw-image-export-windows .` to build the Windows image
- Run `docker run -it -rm -p 8000:8000 c` to start the Windows container and test locally.

To deploy to Azure App Service for Containers on Windows, follow these steps:

1. Login to Azure with the Azure CLI: `az login`
2. Login to the Azure Container Registry: `az acr login --name ${your_registry_name}`
3. Build the image with `docker build -t ${your_registry_name}.azurecr.io/draw-image-export-windows -f Dockerfile.windows .`
4. Push the Docker image to the Azure Container Registry: `docker push ${your_registry_name}.azurecr.io/draw-image-export-windows`

> **If you do not have a Windows container setup, you can use the Azure Container Registry Tasks to build the image in the cloud.**

1. Login to Azure with the Azure CLI: `az login`
2. Login to the Azure Container Registry: `az acr login --name ${your_registry_name}`
3. Run `az acr build -r ${your_registry_name} -t imageexport:latest -f Dockerfile.windows . --platform windows`

## Updating internal draw.io versions (internal only)

* su chrome
* cd ~/draw-image-export2
* git pull
* npm install
* forever restartall
- su chrome
- cd ~/draw-image-export2
- git pull
- npm install
- forever restartall

## Usage

This service accepts the following (url encoded) parameters provided via a HTTP (GET or POST) request. All parameters are optional except where emboldened.

`data-string` means a string of data that has been:

1. deflated _then_
2. base64 encoded _then_
3. url-encoded

There are 2 available modes for the service:

1. _(mode 1)_ Render some html that is provided
2. _(mode 2)_ Render a diagram from some html (which can be provided or retrieved from a given url)

### Mode 1: Provide some html to render

| Argument | Type | Purpose | Default | Example |
| ---- | ---- | ---- | ---- | ---- |
| **html** | data-string | html to render | | - |
| w | number | Set the view port height | 0 | 10 |
| h | number | Set the view port width | 0 | 10 |
| Argument | Type | Purpose | Default | Example |
| -------- | ----------- | ------------------------ | ------- | ------- |
| **html** | data-string | html to render | | - |
| w | number | Set the view port height | 0 | 10 |
| h | number | Set the view port width | 0 | 10 |

Note: Format is fixed to `png` for this mode.

### Mode 2: Render a diagram

To render a diagram, the `diagram-data` must be retrieved, this is the draw.io data that can be used to re-render the diagram. There are 2 modes to get this data:

1. _(mode 2.1)_ Provide a url to a resource
1. _(mode 2.2)_ Provide the data in the request

Whichever option is used the following process will be followed to extract the diagram data:

1. If the data is a XHTML document (well-structured HTML)
1. For the first `div` with the `mxgraph` class defined
1. Use the data in the `data-mxgraph` attribute (if one is present) _OR_
Expand All @@ -53,50 +84,55 @@ Whichever option is used the following process will be followed to extract the d

#### Mode 2.1: Get `diagram-data` from url

| Argument | Type | Purpose | Default | Example |
| ---- | ---- | ---- | ---- | ---- |
| **url** | string | absolute url to diagram to render | | - |
| Argument | Type | Purpose | Default | Example |
| -------- | ------ | --------------------------------- | ------- | ------- |
| **url** | string | absolute url to diagram to render | | - |

#### Mode 2.2: Get `diagram-data` from xml (or svg)

Provide either `xmldata` or `xml`, `xmldata` takes precedence.

| Argument | Type | Purpose | Default | Example |
| ---- | ---- | ---- | ---- | ---- |
| **xmldata** | data-string | Content of the diagram to render | | - |
| **xml** | string (optionally url-encoded) | Content of the diagram to render | | - |
| Argument | Type | Purpose | Default | Example |
| ----------- | ------------------------------- | -------------------------------- | ------- | ------- |
| **xmldata** | data-string | Content of the diagram to render | | - |
| **xml** | string (optionally url-encoded) | Content of the diagram to render | | - |

#### Common parameters
| Argument | Type | Purpose | Default | Example |
| ---- | ---- | ---- | ---- | ---- |
| format§ (see below) | string | The renderering format for the diagram | png | pdf |
| w§ | number | Set the view port height | 0 | 10 |
| h§ | number | Set the view port width | 0 | 10 |
| embedXml* | string | Embed the diagram data in the png | | "0" or "1" |
| base64 | string | Whether the response data should be base64 (and png embedded data) encoded | | "0" or "1" |
| bg§ | string | The background colour for the image | | "#ff8888" |
| embedData* | string | Embed `data` in the png with the `dataHeader` key | null | "0" or "1" |
| data* | string | The data to embed into the png | | - |
| dataHeader* | string | The key to use when embedding the `data` into the png | | "myKey" |
| filename | string | The filename to included in the content-disposition header | | "myFile.png" |
| border¶ | number | The size of the border for the page | 0 | 10 |
| from¶ | number | The index of the page to start rendering from | | 1 |
| to¶ | number | The index of the page to finish rendering at | | 2 |
| pageId¶ | string | The id of the page to render | | "page id" |
| allPages¶ | string | Whether all pages should be rendered | "0" | "0" or "1" |
| scale¶ | number | The scale for the rendered diagram | 1 | 1.5 |
| extras¶ | json-string | Additional detail how what should be rendered, e.g. layer-names | | ? |

| Argument | Type | Purpose | Default | Example |
| ------------------- | ----------- | -------------------------------------------------------------------------- | ------- | ------------ |
| format§ (see below) | string | The renderering format for the diagram | png | pdf |
| w§ | number | Set the view port height | 0 | 10 |
| h§ | number | Set the view port width | 0 | 10 |
| embedXml\* | string | Embed the diagram data in the png | | "0" or "1" |
| base64 | string | Whether the response data should be base64 (and png embedded data) encoded | | "0" or "1" |
| bg§ | string | The background colour for the image | | "#ff8888" |
| embedData\* | string | Embed `data` in the png with the `dataHeader` key | null | "0" or "1" |
| data\* | string | The data to embed into the png | | - |
| dataHeader\* | string | The key to use when embedding the `data` into the png | | "myKey" |
| filename | string | The filename to included in the content-disposition header | | "myFile.png" |
| border¶ | number | The size of the border for the page | 0 | 10 |
| from¶ | number | The index of the page to start rendering from | | 1 |
| to¶ | number | The index of the page to finish rendering at | | 2 |
| pageId¶ | string | The id of the page to render | | "page id" |
| allPages¶ | string | Whether all pages should be rendered | "0" | "0" or "1" |
| scale¶ | number | The scale for the rendered diagram | 1 | 1.5 |
| extras¶ | json-string | Additional detail how what should be rendered, e.g. layer-names | | ? |

\* Only applicable when format is `png`.
§ means property is used by both this service and draw.io (https://www.draw.io/export3.html) to control how the diagram is rendered.
¶ means property is passed to draw.io (https://www.draw.io/export3.html) to control how the diagram is rendered.

### Formats

The following formats can be used

- 'png' (default)
- 'jpg' (or 'jpeg')
- 'pdf'

## Examples

### Example 1 (render a diagram in png format from provided diagram data)

```
Expand All @@ -110,6 +146,8 @@ format=png&xml=%3Cmxfile+...

### Example 2 (render a diagram in png format from provided url - to a diagram file)

> ⚠️ Export by URL is currently disabled!

```
GET https://exp-pdf.draw.io/ImageExport4/export?format=png&bg=ffffff&url=https://somewhere/diagram.xml HTTP/1.1
Host: exp-pdf.draw.io
Expand Down
5 changes: 5 additions & 0 deletions export.js
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ else
}

app.post('/{*splat}', handleRequest);
app.get('/health', handleHealthRequest);
app.get('/{*splat}', handleRequest);

async function handleRequest(req, res)
Expand Down Expand Up @@ -770,6 +771,10 @@ else
}
};

async function handleHealthRequest(req, res) {
res.status(200).end("OK");
}

app.listen(PORT, function ()
{
if (NO_CLUSTER)
Expand Down