orator-conversion 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dockerignore +15 -0
- package/.vscode/launch.json +47 -0
- package/Dockerfile +60 -0
- package/LICENSE +21 -0
- package/README.md +166 -0
- package/debug/Harness.js +48 -0
- package/debug/PostJPGToDebugServer.sh +44 -0
- package/debug/PostPDFToDebugServer.sh +54 -0
- package/debug/PostPNGToDebugServer.sh +44 -0
- package/docs/.nojekyll +0 -0
- package/docs/README.md +68 -0
- package/docs/_sidebar.md +16 -0
- package/docs/api-reference.md +146 -0
- package/docs/configuration.md +77 -0
- package/docs/cover.md +13 -0
- package/docs/endpoints/001-jpg-to-png.md +60 -0
- package/docs/endpoints/002-png-to-jpg.md +60 -0
- package/docs/endpoints/003-pdf-to-page-png.md +93 -0
- package/docs/endpoints/004-pdf-to-page-jpg.md +94 -0
- package/docs/endpoints/README.md +75 -0
- package/docs/getting-started.md +113 -0
- package/docs/index.html +39 -0
- package/package.json +55 -0
- package/source/Orator-File-Translation.js +504 -0
- package/source/endpoints/Endpoint-Image-JpgToPng.js +34 -0
- package/source/endpoints/Endpoint-Image-PngToJpg.js +34 -0
- package/source/endpoints/Endpoint-Pdf-PageToJpg-Sized.js +43 -0
- package/source/endpoints/Endpoint-Pdf-PageToJpg.js +36 -0
- package/source/endpoints/Endpoint-Pdf-PageToPng-Sized.js +43 -0
- package/source/endpoints/Endpoint-Pdf-PageToPng.js +36 -0
- package/test/Orator-File-Translation_basic_tests.js +371 -0
- package/test/Orator-File-Translation_tests.js +694 -0
package/.dockerignore
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
// Use IntelliSense to learn about possible attributes.
|
|
3
|
+
// Hover to view descriptions of existing attributes.
|
|
4
|
+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
5
|
+
"version": "0.2.0",
|
|
6
|
+
"configurations": [
|
|
7
|
+
{
|
|
8
|
+
"name": "Launch Debug Harness",
|
|
9
|
+
"type": "node",
|
|
10
|
+
"request": "launch",
|
|
11
|
+
"outputCapture": "std",
|
|
12
|
+
"skipFiles": [
|
|
13
|
+
"<node_internals>/**"
|
|
14
|
+
],
|
|
15
|
+
"cwd": "${workspaceFolder}/debug/",
|
|
16
|
+
"program": "${workspaceFolder}/debug/Harness.js",
|
|
17
|
+
"presentation": {
|
|
18
|
+
"hidden": false,
|
|
19
|
+
"group": "",
|
|
20
|
+
"order": 1
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"name": "Mocha Tests",
|
|
25
|
+
"args": [
|
|
26
|
+
"-u",
|
|
27
|
+
"tdd",
|
|
28
|
+
"--timeout",
|
|
29
|
+
"999999",
|
|
30
|
+
"--colors",
|
|
31
|
+
"${workspaceFolder}/test"
|
|
32
|
+
],
|
|
33
|
+
"internalConsoleOptions": "openOnSessionStart",
|
|
34
|
+
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
|
|
35
|
+
"request": "launch",
|
|
36
|
+
"skipFiles": [
|
|
37
|
+
"<node_internals>/**"
|
|
38
|
+
],
|
|
39
|
+
"type": "pwa-node",
|
|
40
|
+
"presentation": {
|
|
41
|
+
"hidden": false,
|
|
42
|
+
"group": "",
|
|
43
|
+
"order": 2
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
package/Dockerfile
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Orator File Translation
|
|
2
|
+
# Production image for file format conversion (image + PDF page extraction)
|
|
3
|
+
#
|
|
4
|
+
# Ubuntu is preferred over Alpine for PDF rendering because:
|
|
5
|
+
# - poppler-utils has better font rendering with glibc
|
|
6
|
+
# - More complete font packages for accurate PDF rasterization
|
|
7
|
+
# - sharp (libvips) builds more reliably on Debian-based images
|
|
8
|
+
# - pdftk-java is readily available
|
|
9
|
+
#
|
|
10
|
+
# Build:
|
|
11
|
+
# docker build -t orator-conversion .
|
|
12
|
+
#
|
|
13
|
+
# Run:
|
|
14
|
+
# docker run -p 8765:8765 orator-conversion
|
|
15
|
+
#
|
|
16
|
+
# Test:
|
|
17
|
+
# curl -X POST --data-binary @photo.jpg \
|
|
18
|
+
# -H "Content-Type: application/octet-stream" \
|
|
19
|
+
# http://localhost:8765/conversion/1.0/image/jpg-to-png -o photo.png
|
|
20
|
+
|
|
21
|
+
FROM node:22-bookworm-slim
|
|
22
|
+
|
|
23
|
+
LABEL maintainer="steven velozo <steven@velozo.com>"
|
|
24
|
+
LABEL description="Orator File Translation - file format conversion service"
|
|
25
|
+
|
|
26
|
+
# Install system dependencies for PDF rendering and image processing
|
|
27
|
+
# poppler-utils - provides pdftoppm for PDF page rasterization
|
|
28
|
+
# pdftk-java - provides pdftk for PDF page extraction
|
|
29
|
+
# fonts-dejavu - base fonts for PDF rendering
|
|
30
|
+
# fontconfig - font configuration for consistent rendering
|
|
31
|
+
RUN apt-get update \
|
|
32
|
+
&& apt-get install -y --no-install-recommends \
|
|
33
|
+
poppler-utils \
|
|
34
|
+
pdftk-java \
|
|
35
|
+
fonts-dejavu-core \
|
|
36
|
+
fontconfig \
|
|
37
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
38
|
+
|
|
39
|
+
# Rebuild the font cache so pdftoppm can find system fonts
|
|
40
|
+
RUN fc-cache -f -v
|
|
41
|
+
|
|
42
|
+
WORKDIR /usr/src/app
|
|
43
|
+
|
|
44
|
+
# Copy package files first for better layer caching
|
|
45
|
+
COPY package.json ./
|
|
46
|
+
|
|
47
|
+
# Install all dependencies (including devDependencies needed for the harness)
|
|
48
|
+
RUN npm install --production=false
|
|
49
|
+
|
|
50
|
+
# Copy application source
|
|
51
|
+
COPY source/ ./source/
|
|
52
|
+
COPY debug/Harness.js ./debug/Harness.js
|
|
53
|
+
|
|
54
|
+
EXPOSE 8765
|
|
55
|
+
|
|
56
|
+
# Health check against one of the conversion endpoints
|
|
57
|
+
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
|
58
|
+
CMD node -e "const h=require('http');const r=h.request({hostname:'127.0.0.1',port:8765,path:'/conversion/1.0/image/jpg-to-png',method:'POST',timeout:3000},(s)=>{process.exit(s.statusCode===400?0:1)});r.on('error',()=>process.exit(1));r.end();"
|
|
59
|
+
|
|
60
|
+
CMD ["node", "debug/Harness.js"]
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Steven Velozo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Orator File Translation
|
|
2
|
+
|
|
3
|
+
> File format conversion endpoints for Orator service servers
|
|
4
|
+
|
|
5
|
+
Orator File Translation provides a simple way to add file format conversion endpoints to an Orator web server. It ships with built-in image converters (JPG to PNG, PNG to JPG), PDF page extraction (PDF to PNG/JPG via pdftoppm), and supports registering custom converters for any file format. All routes are versioned.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Image Conversion** - Convert between JPG and PNG formats via HTTP POST endpoints
|
|
10
|
+
- **PDF Page Extraction** - Extract individual pages from PDFs as PNG or JPEG images
|
|
11
|
+
- **Versioned Routes** - All endpoints include a configurable version segment
|
|
12
|
+
- **Extensible** - Register custom converters for any file format via `addConverter()`
|
|
13
|
+
- **Configurable** - Settings via constructor options or Fable settings
|
|
14
|
+
- **Size Limits** - Configurable maximum file size to prevent abuse
|
|
15
|
+
- **Fable Service Provider** - Registers as a standard Fable service
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```javascript
|
|
20
|
+
const libFable = require('fable');
|
|
21
|
+
const libOrator = require('orator');
|
|
22
|
+
const libOratorServiceServerRestify = require('orator-serviceserver-restify');
|
|
23
|
+
const libOratorFileTranslation = require('orator-conversion');
|
|
24
|
+
|
|
25
|
+
const _Fable = new libFable({
|
|
26
|
+
Product: 'MyConversionServer',
|
|
27
|
+
APIServerPort: 8080
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Set up Orator with Restify
|
|
31
|
+
_Fable.serviceManager.addServiceType('Orator', libOrator);
|
|
32
|
+
_Fable.serviceManager.addServiceType('OratorServiceServer', libOratorServiceServerRestify);
|
|
33
|
+
_Fable.serviceManager.instantiateServiceProvider('Orator');
|
|
34
|
+
_Fable.serviceManager.instantiateServiceProvider('OratorServiceServer');
|
|
35
|
+
|
|
36
|
+
// Set up file translation
|
|
37
|
+
_Fable.serviceManager.addServiceType('OratorFileTranslation', libOratorFileTranslation);
|
|
38
|
+
_Fable.serviceManager.instantiateServiceProvider('OratorFileTranslation');
|
|
39
|
+
|
|
40
|
+
// Initialize and start
|
|
41
|
+
_Fable.Orator.startService(
|
|
42
|
+
() =>
|
|
43
|
+
{
|
|
44
|
+
_Fable.OratorFileTranslation.connectRoutes();
|
|
45
|
+
// POST http://localhost:8080/conversion/1.0/image/jpg-to-png
|
|
46
|
+
// POST http://localhost:8080/conversion/1.0/image/png-to-jpg
|
|
47
|
+
// POST http://localhost:8080/conversion/1.0/pdf-to-page-png/:Page
|
|
48
|
+
// POST http://localhost:8080/conversion/1.0/pdf-to-page-jpg/:Page
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Installation
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npm install orator-conversion
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### System Dependencies
|
|
59
|
+
|
|
60
|
+
PDF page extraction requires `pdftoppm` (part of the poppler-utils package):
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# macOS
|
|
64
|
+
brew install poppler
|
|
65
|
+
|
|
66
|
+
# Debian/Ubuntu
|
|
67
|
+
apt-get install poppler-utils
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Configuration
|
|
71
|
+
|
|
72
|
+
| Setting | Type | Default | Description |
|
|
73
|
+
|---------|------|---------|-------------|
|
|
74
|
+
| `RoutePrefix` | string | `"/conversion"` | URL prefix for conversion endpoints |
|
|
75
|
+
| `Version` | string | `"1.0"` | Version segment in route URLs |
|
|
76
|
+
| `LogLevel` | number | `0` | Logging verbosity (higher = more output) |
|
|
77
|
+
| `MaxFileSize` | number | `10485760` | Maximum upload size in bytes (default 10MB) |
|
|
78
|
+
| `PdftkPath` | string | `"pdftk"` | Path to the pdftk binary |
|
|
79
|
+
| `PdftoppmPath` | string | `"pdftoppm"` | Path to the pdftoppm binary |
|
|
80
|
+
|
|
81
|
+
Settings can also be provided via Fable settings:
|
|
82
|
+
|
|
83
|
+
| Fable Setting | Maps To |
|
|
84
|
+
|---------------|---------|
|
|
85
|
+
| `OratorFileTranslationRoutePrefix` | `RoutePrefix` |
|
|
86
|
+
| `OratorFileTranslationVersion` | `Version` |
|
|
87
|
+
| `OratorFileTranslationLogLevel` | `LogLevel` |
|
|
88
|
+
| `OratorFileTranslationMaxFileSize` | `MaxFileSize` |
|
|
89
|
+
| `OratorFileTranslationPdftkPath` | `PdftkPath` |
|
|
90
|
+
| `OratorFileTranslationPdftoppmPath` | `PdftoppmPath` |
|
|
91
|
+
|
|
92
|
+
## API
|
|
93
|
+
|
|
94
|
+
### connectRoutes()
|
|
95
|
+
|
|
96
|
+
Register POST endpoints on the Orator service server for each registered converter. Routes are versioned: `{RoutePrefix}/{Version}/{converterPath}`. Call this after Orator has been started.
|
|
97
|
+
|
|
98
|
+
```javascript
|
|
99
|
+
_Fable.OratorFileTranslation.connectRoutes();
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### addConverter(pPath, fConverter)
|
|
103
|
+
|
|
104
|
+
Register a custom converter. The path becomes part of the endpoint URL (`{RoutePrefix}/{Version}/{pPath}`). The converter function receives the input buffer, the request object, and a callback.
|
|
105
|
+
|
|
106
|
+
```javascript
|
|
107
|
+
_Fable.OratorFileTranslation.addConverter('document/csv-to-json',
|
|
108
|
+
(pInputBuffer, pRequest, fCallback) =>
|
|
109
|
+
{
|
|
110
|
+
let tmpCSV = pInputBuffer.toString('utf8');
|
|
111
|
+
let tmpJSON = convertCSVToJSON(tmpCSV);
|
|
112
|
+
return fCallback(null, Buffer.from(JSON.stringify(tmpJSON)), 'application/json');
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### extractPdfPage(pPdfBuffer, pPageNumber, fCallback)
|
|
117
|
+
|
|
118
|
+
Extract a single page from a PDF buffer using pdftk, returning the single-page PDF as a buffer.
|
|
119
|
+
|
|
120
|
+
### renderPdfPageToImage(pPdfBuffer, pPageNumber, pFormat, fCallback)
|
|
121
|
+
|
|
122
|
+
Render a specific page of a PDF to an image buffer using pdftoppm. The `pFormat` parameter can be `'png'` or `'jpeg'`.
|
|
123
|
+
|
|
124
|
+
## Endpoints
|
|
125
|
+
|
|
126
|
+
All endpoints are versioned. Conversion endpoints accept raw binary data via POST and return the converted file:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
# Convert JPG to PNG
|
|
130
|
+
curl -X POST --data-binary @photo.jpg \
|
|
131
|
+
-H "Content-Type: application/octet-stream" \
|
|
132
|
+
http://localhost:8080/conversion/1.0/image/jpg-to-png \
|
|
133
|
+
-o photo.png
|
|
134
|
+
|
|
135
|
+
# Convert PNG to JPG
|
|
136
|
+
curl -X POST --data-binary @image.png \
|
|
137
|
+
-H "Content-Type: application/octet-stream" \
|
|
138
|
+
http://localhost:8080/conversion/1.0/image/png-to-jpg \
|
|
139
|
+
-o image.jpg
|
|
140
|
+
|
|
141
|
+
# Extract page 1 from a PDF as PNG
|
|
142
|
+
curl -X POST --data-binary @document.pdf \
|
|
143
|
+
-H "Content-Type: application/octet-stream" \
|
|
144
|
+
http://localhost:8080/conversion/1.0/pdf-to-page-png/1 \
|
|
145
|
+
-o page1.png
|
|
146
|
+
|
|
147
|
+
# Extract page 3 from a PDF as JPEG
|
|
148
|
+
curl -X POST --data-binary @document.pdf \
|
|
149
|
+
-H "Content-Type: application/octet-stream" \
|
|
150
|
+
http://localhost:8080/conversion/1.0/pdf-to-page-jpg/3 \
|
|
151
|
+
-o page3.jpg
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Documentation
|
|
155
|
+
|
|
156
|
+
Full documentation is available in the [`docs`](./docs) folder, or served locally:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
npx docsify-cli serve docs
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Related Packages
|
|
163
|
+
|
|
164
|
+
- [orator](https://github.com/stevenvelozo/orator) - Main Orator service abstraction
|
|
165
|
+
- [orator-serviceserver-restify](https://github.com/stevenvelozo/orator-serviceserver-restify) - Restify service server
|
|
166
|
+
- [fable](https://github.com/stevenvelozo/fable) - Service provider framework
|
package/debug/Harness.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const libFable = require('fable');
|
|
2
|
+
|
|
3
|
+
const defaultFableSettings = (
|
|
4
|
+
{
|
|
5
|
+
Product: 'Orator-FileTranslation',
|
|
6
|
+
ProductVersion: '1.0.0',
|
|
7
|
+
APIServerPort: 8765
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
let _Fable = new libFable(defaultFableSettings);
|
|
11
|
+
|
|
12
|
+
_Fable.serviceManager.addServiceType('OratorServiceServer', require('orator-serviceserver-restify'));
|
|
13
|
+
_Fable.serviceManager.instantiateServiceProvider('OratorServiceServer', {});
|
|
14
|
+
|
|
15
|
+
_Fable.serviceManager.addServiceType('Orator', require('orator'));
|
|
16
|
+
let _Orator = _Fable.serviceManager.instantiateServiceProvider('Orator', {});
|
|
17
|
+
|
|
18
|
+
const libOratorFileTranslation = require('../source/Orator-File-Translation.js');
|
|
19
|
+
_Fable.serviceManager.addServiceType('OratorFileTranslation', libOratorFileTranslation);
|
|
20
|
+
_Fable.serviceManager.instantiateServiceProvider('OratorFileTranslation', { LogLevel: 2 });
|
|
21
|
+
|
|
22
|
+
let tmpAnticipate = _Fable.newAnticipate();
|
|
23
|
+
|
|
24
|
+
tmpAnticipate.anticipate(_Orator.initialize.bind(_Orator));
|
|
25
|
+
|
|
26
|
+
tmpAnticipate.anticipate(
|
|
27
|
+
(fNext) =>
|
|
28
|
+
{
|
|
29
|
+
_Fable.OratorFileTranslation.connectRoutes();
|
|
30
|
+
return fNext();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
tmpAnticipate.anticipate(_Orator.startService.bind(_Orator));
|
|
34
|
+
|
|
35
|
+
tmpAnticipate.wait(
|
|
36
|
+
(pError) =>
|
|
37
|
+
{
|
|
38
|
+
if (pError)
|
|
39
|
+
{
|
|
40
|
+
_Fable.log.error('Error initializing Orator Service Server: ' + pError.message, pError);
|
|
41
|
+
}
|
|
42
|
+
_Fable.log.info('Orator File Translation Service Server Initialized.');
|
|
43
|
+
_Fable.log.info('Available endpoints:');
|
|
44
|
+
_Fable.log.info(' POST http://127.0.0.1:8765/conversion/1.0/image/jpg-to-png');
|
|
45
|
+
_Fable.log.info(' POST http://127.0.0.1:8765/conversion/1.0/image/png-to-jpg');
|
|
46
|
+
_Fable.log.info(' POST http://127.0.0.1:8765/conversion/1.0/pdf-to-page-png/:Page');
|
|
47
|
+
_Fable.log.info(' POST http://127.0.0.1:8765/conversion/1.0/pdf-to-page-jpg/:Page');
|
|
48
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Post a JPG file to the debug conversion server and save the PNG result
|
|
3
|
+
# Usage: bash PostJPGToDebugServer.sh <input.jpg>
|
|
4
|
+
|
|
5
|
+
if [ -z "$1" ]; then
|
|
6
|
+
echo "Usage: $0 <input_jpg_file>"
|
|
7
|
+
echo " Posts a JPG file to the debug server for conversion to PNG."
|
|
8
|
+
echo " The debug server (Harness.js) must be running on port 8765."
|
|
9
|
+
exit 1
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
INPUT_FILE="$1"
|
|
13
|
+
|
|
14
|
+
if [ ! -f "$INPUT_FILE" ]; then
|
|
15
|
+
echo "Error: File not found: $INPUT_FILE"
|
|
16
|
+
exit 1
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
# Extract the base filename without extension
|
|
20
|
+
BASENAME=$(basename "$INPUT_FILE")
|
|
21
|
+
NAME_NO_EXT="${BASENAME%.*}"
|
|
22
|
+
|
|
23
|
+
# Generate timestamp: YYYY_MM_DD_HH_MM_SS_MS
|
|
24
|
+
TIMESTAMP=$(date +%Y_%m_%d_%H_%M_%S)
|
|
25
|
+
# Append milliseconds (cross-platform via python3)
|
|
26
|
+
MS=$(python3 -c "import datetime; print(f'{datetime.datetime.now().microsecond // 1000:03d}')")
|
|
27
|
+
TIMESTAMP="${TIMESTAMP}_${MS}"
|
|
28
|
+
|
|
29
|
+
OUTPUT_FILE="${NAME_NO_EXT}_${TIMESTAMP}.png"
|
|
30
|
+
|
|
31
|
+
echo "Converting ${INPUT_FILE} (JPG) -> ${OUTPUT_FILE} (PNG) ..."
|
|
32
|
+
|
|
33
|
+
curl -s -X POST \
|
|
34
|
+
--data-binary @"${INPUT_FILE}" \
|
|
35
|
+
-H "Content-Type: application/octet-stream" \
|
|
36
|
+
http://127.0.0.1:8765/conversion/1.0/image/jpg-to-png \
|
|
37
|
+
-o "${OUTPUT_FILE}"
|
|
38
|
+
|
|
39
|
+
if [ $? -eq 0 ] && [ -f "$OUTPUT_FILE" ] && [ -s "$OUTPUT_FILE" ]; then
|
|
40
|
+
echo "Success: ${OUTPUT_FILE}"
|
|
41
|
+
else
|
|
42
|
+
echo "Error: Conversion failed."
|
|
43
|
+
exit 1
|
|
44
|
+
fi
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Post a PDF file to the debug conversion server and save a page as PNG
|
|
3
|
+
# Usage: bash PostPDFToDebugServer.sh <input.pdf> [page_number] [format]
|
|
4
|
+
|
|
5
|
+
if [ -z "$1" ]; then
|
|
6
|
+
echo "Usage: $0 <input_pdf_file> [page_number] [format]"
|
|
7
|
+
echo " Posts a PDF file to the debug server for page extraction."
|
|
8
|
+
echo " page_number: The page to extract (default: 1)"
|
|
9
|
+
echo " format: png or jpg (default: png)"
|
|
10
|
+
echo " The debug server (Harness.js) must be running on port 8765."
|
|
11
|
+
exit 1
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
INPUT_FILE="$1"
|
|
15
|
+
PAGE="${2:-1}"
|
|
16
|
+
FORMAT="${3:-png}"
|
|
17
|
+
|
|
18
|
+
if [ ! -f "$INPUT_FILE" ]; then
|
|
19
|
+
echo "Error: File not found: $INPUT_FILE"
|
|
20
|
+
exit 1
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
# Validate format
|
|
24
|
+
if [ "$FORMAT" != "png" ] && [ "$FORMAT" != "jpg" ]; then
|
|
25
|
+
echo "Error: Format must be 'png' or 'jpg'"
|
|
26
|
+
exit 1
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
# Extract the base filename without extension
|
|
30
|
+
BASENAME=$(basename "$INPUT_FILE")
|
|
31
|
+
NAME_NO_EXT="${BASENAME%.*}"
|
|
32
|
+
|
|
33
|
+
# Generate timestamp: YYYY_MM_DD_HH_MM_SS_MS
|
|
34
|
+
TIMESTAMP=$(date +%Y_%m_%d_%H_%M_%S)
|
|
35
|
+
# Append milliseconds (cross-platform via python3)
|
|
36
|
+
MS=$(python3 -c "import datetime; print(f'{datetime.datetime.now().microsecond // 1000:03d}')")
|
|
37
|
+
TIMESTAMP="${TIMESTAMP}_${MS}"
|
|
38
|
+
|
|
39
|
+
OUTPUT_FILE="${NAME_NO_EXT}_page${PAGE}_${TIMESTAMP}.${FORMAT}"
|
|
40
|
+
|
|
41
|
+
echo "Extracting page ${PAGE} from ${INPUT_FILE} (PDF) -> ${OUTPUT_FILE} (${FORMAT}) ..."
|
|
42
|
+
|
|
43
|
+
curl -s -X POST \
|
|
44
|
+
--data-binary @"${INPUT_FILE}" \
|
|
45
|
+
-H "Content-Type: application/octet-stream" \
|
|
46
|
+
http://127.0.0.1:8765/conversion/1.0/pdf-to-page-${FORMAT}/${PAGE} \
|
|
47
|
+
-o "${OUTPUT_FILE}"
|
|
48
|
+
|
|
49
|
+
if [ $? -eq 0 ] && [ -f "$OUTPUT_FILE" ] && [ -s "$OUTPUT_FILE" ]; then
|
|
50
|
+
echo "Success: ${OUTPUT_FILE}"
|
|
51
|
+
else
|
|
52
|
+
echo "Error: Conversion failed."
|
|
53
|
+
exit 1
|
|
54
|
+
fi
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Post a PNG file to the debug conversion server and save the JPG result
|
|
3
|
+
# Usage: bash PostPNGToDebugServer.sh <input.png>
|
|
4
|
+
|
|
5
|
+
if [ -z "$1" ]; then
|
|
6
|
+
echo "Usage: $0 <input_png_file>"
|
|
7
|
+
echo " Posts a PNG file to the debug server for conversion to JPG."
|
|
8
|
+
echo " The debug server (Harness.js) must be running on port 8765."
|
|
9
|
+
exit 1
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
INPUT_FILE="$1"
|
|
13
|
+
|
|
14
|
+
if [ ! -f "$INPUT_FILE" ]; then
|
|
15
|
+
echo "Error: File not found: $INPUT_FILE"
|
|
16
|
+
exit 1
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
# Extract the base filename without extension
|
|
20
|
+
BASENAME=$(basename "$INPUT_FILE")
|
|
21
|
+
NAME_NO_EXT="${BASENAME%.*}"
|
|
22
|
+
|
|
23
|
+
# Generate timestamp: YYYY_MM_DD_HH_MM_SS_MS
|
|
24
|
+
TIMESTAMP=$(date +%Y_%m_%d_%H_%M_%S)
|
|
25
|
+
# Append milliseconds (cross-platform via python3)
|
|
26
|
+
MS=$(python3 -c "import datetime; print(f'{datetime.datetime.now().microsecond // 1000:03d}')")
|
|
27
|
+
TIMESTAMP="${TIMESTAMP}_${MS}"
|
|
28
|
+
|
|
29
|
+
OUTPUT_FILE="${NAME_NO_EXT}_${TIMESTAMP}.jpg"
|
|
30
|
+
|
|
31
|
+
echo "Converting ${INPUT_FILE} (PNG) -> ${OUTPUT_FILE} (JPG) ..."
|
|
32
|
+
|
|
33
|
+
curl -s -X POST \
|
|
34
|
+
--data-binary @"${INPUT_FILE}" \
|
|
35
|
+
-H "Content-Type: application/octet-stream" \
|
|
36
|
+
http://127.0.0.1:8765/conversion/1.0/image/png-to-jpg \
|
|
37
|
+
-o "${OUTPUT_FILE}"
|
|
38
|
+
|
|
39
|
+
if [ $? -eq 0 ] && [ -f "$OUTPUT_FILE" ] && [ -s "$OUTPUT_FILE" ]; then
|
|
40
|
+
echo "Success: ${OUTPUT_FILE}"
|
|
41
|
+
else
|
|
42
|
+
echo "Error: Conversion failed."
|
|
43
|
+
exit 1
|
|
44
|
+
fi
|
package/docs/.nojekyll
ADDED
|
File without changes
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Orator File Translation
|
|
2
|
+
|
|
3
|
+
> File format conversion endpoints for Orator service servers
|
|
4
|
+
|
|
5
|
+
Orator File Translation adds file format conversion endpoints to an Orator web server. Upload a file via HTTP POST and receive the converted file in the response. All routes are versioned.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Image Conversion** - Convert between JPG and PNG formats
|
|
10
|
+
- **PDF Page Extraction** - Extract individual pages from PDFs as PNG or JPEG
|
|
11
|
+
- **Versioned Routes** - All endpoints include a configurable version segment
|
|
12
|
+
- **Extensible** - Add custom converters for any file format
|
|
13
|
+
- **Configurable** - Route prefix, version, logging, and file size limits
|
|
14
|
+
- **Fable Service** - Standard Fable service provider pattern
|
|
15
|
+
|
|
16
|
+
## How It Works
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
Client Orator Server pdftoppm/Sharp
|
|
20
|
+
| | |
|
|
21
|
+
| POST /conversion/1.0/ | |
|
|
22
|
+
| image/jpg-to-png | |
|
|
23
|
+
| [binary JPEG data] | |
|
|
24
|
+
| --------------------------> | |
|
|
25
|
+
| | sharp(buffer).png() |
|
|
26
|
+
| | -------------------------> |
|
|
27
|
+
| | |
|
|
28
|
+
| | [PNG buffer] |
|
|
29
|
+
| | <------------------------- |
|
|
30
|
+
| 200 OK | |
|
|
31
|
+
| Content-Type: image/png | |
|
|
32
|
+
| [binary PNG data] | |
|
|
33
|
+
| <-------------------------- | |
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Quick Start
|
|
37
|
+
|
|
38
|
+
```javascript
|
|
39
|
+
const libFable = require('fable');
|
|
40
|
+
const libOrator = require('orator');
|
|
41
|
+
const libOratorServiceServerRestify = require('orator-serviceserver-restify');
|
|
42
|
+
const libOratorFileTranslation = require('orator-conversion');
|
|
43
|
+
|
|
44
|
+
const _Fable = new libFable({
|
|
45
|
+
Product: 'MyConversionServer',
|
|
46
|
+
APIServerPort: 8080
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
_Fable.serviceManager.addServiceType('Orator', libOrator);
|
|
50
|
+
_Fable.serviceManager.addServiceType('OratorServiceServer', libOratorServiceServerRestify);
|
|
51
|
+
_Fable.serviceManager.instantiateServiceProvider('Orator');
|
|
52
|
+
_Fable.serviceManager.instantiateServiceProvider('OratorServiceServer');
|
|
53
|
+
|
|
54
|
+
_Fable.serviceManager.addServiceType('OratorFileTranslation', libOratorFileTranslation);
|
|
55
|
+
_Fable.serviceManager.instantiateServiceProvider('OratorFileTranslation');
|
|
56
|
+
|
|
57
|
+
_Fable.Orator.startService(
|
|
58
|
+
() =>
|
|
59
|
+
{
|
|
60
|
+
_Fable.OratorFileTranslation.connectRoutes();
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Related Packages
|
|
65
|
+
|
|
66
|
+
- [orator](https://github.com/stevenvelozo/orator) - Main Orator service abstraction
|
|
67
|
+
- [orator-serviceserver-restify](https://github.com/stevenvelozo/orator-serviceserver-restify) - Restify service server
|
|
68
|
+
- [fable](https://github.com/stevenvelozo/fable) - Service provider framework
|
package/docs/_sidebar.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
- Getting Started
|
|
2
|
+
|
|
3
|
+
- [Introduction](/)
|
|
4
|
+
- [Getting Started](getting-started.md)
|
|
5
|
+
|
|
6
|
+
- Reference
|
|
7
|
+
|
|
8
|
+
- [Configuration](configuration.md)
|
|
9
|
+
- [API Reference](api-reference.md)
|
|
10
|
+
|
|
11
|
+
- Endpoints
|
|
12
|
+
|
|
13
|
+
- [JPG to PNG](endpoints/001-jpg-to-png.md)
|
|
14
|
+
- [PNG to JPG](endpoints/002-png-to-jpg.md)
|
|
15
|
+
- [PDF to Page PNG](endpoints/003-pdf-to-page-png.md)
|
|
16
|
+
- [PDF to Page JPG](endpoints/004-pdf-to-page-jpg.md)
|