2024-07-01 03:59:01 +00:00
|
|
|
#!/bin/bash
|
|
|
|
# https://docs.sheetjs.com/docs/demos/net/server#worker-threads
|
|
|
|
|
|
|
|
cd /tmp
|
|
|
|
rm -rf sheetjs-worker
|
|
|
|
|
|
|
|
mkdir sheetjs-worker
|
|
|
|
cd sheetjs-worker
|
|
|
|
echo '{ "type": "module" }' > package.json
|
|
|
|
|
2024-07-18 22:19:02 +00:00
|
|
|
npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz express@4.18.2 formidable@2.1.2
|
2024-07-01 03:59:01 +00:00
|
|
|
|
|
|
|
cat >worker.js <<EOF
|
|
|
|
/* load the worker_threads module */
|
|
|
|
import { parentPort } from 'node:worker_threads';
|
|
|
|
|
|
|
|
/* load the SheetJS module and hook to FS */
|
|
|
|
import { set_fs, readFile, write } from 'xlsx';
|
|
|
|
import * as fs from 'fs';
|
|
|
|
set_fs(fs);
|
|
|
|
|
|
|
|
/* the server will send a message with the \`path\` field */
|
|
|
|
parentPort.on('message', (task) => {
|
|
|
|
// read file
|
|
|
|
const wb = readFile(task.path, { dense: true });
|
|
|
|
// send back XLSX
|
|
|
|
parentPort.postMessage(write(wb, { type: "buffer", bookType: "xlsx" }));
|
|
|
|
// remove file
|
|
|
|
fs.unlink(task.path, ()=>{});
|
|
|
|
});
|
|
|
|
EOF
|
|
|
|
|
|
|
|
curl -LO https://docs.sheetjs.com/server/worker_pool.js
|
|
|
|
curl -LO https://docs.sheetjs.com/pres.numbers
|
|
|
|
|
|
|
|
cat >main.mjs <<EOF
|
|
|
|
/* load dependencies */
|
|
|
|
import os from 'node:os';
|
|
|
|
import process from 'node:process'
|
|
|
|
import express from 'express';
|
|
|
|
import formidable from 'formidable';
|
|
|
|
|
|
|
|
/* load worker pool */
|
|
|
|
import WorkerPool from './worker_pool.js';
|
|
|
|
|
|
|
|
const pool = new WorkerPool(os.cpus().length);
|
|
|
|
process.on("beforeExit", () => { pool.close(); })
|
|
|
|
|
|
|
|
/* create server */
|
|
|
|
const app = express();
|
|
|
|
app.post('/', (req, res, next) => {
|
|
|
|
// parse body
|
|
|
|
const form = formidable({});
|
|
|
|
form.parse(req, (err, fields, files) => {
|
|
|
|
// look for "upload" field
|
|
|
|
if(err) return next(err);
|
|
|
|
if(!files["upload"]) return next(new Error("missing \`upload\` file"));
|
|
|
|
|
|
|
|
// send a message to the worker with the path to the uploaded file
|
|
|
|
pool.runTask({ path: files["upload"].filepath }, (err, result) => {
|
|
|
|
if(err) return next(err);
|
|
|
|
// send the file back as an attachment
|
|
|
|
res.attachment("SheetJSPool.xlsx");
|
|
|
|
res.status(200).end(result);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
// start server
|
|
|
|
app.listen(7262, () => { console.log(\`Example app listening on port 7262\`); });
|
|
|
|
EOF
|
|
|
|
|
|
|
|
# this version uses `n` to cycle through node versions
|
|
|
|
for n in 18 20 22; do
|
|
|
|
sudo n $n
|
|
|
|
node --version
|
|
|
|
npx -y concurrently -k 'node main.mjs' 'sleep 2; curl -X POST -F upload=@pres.numbers http://localhost:7262/ -J -O'
|
|
|
|
npx -y xlsx-cli SheetJSPool.xlsx
|
|
|
|
rm -f SheetJSPool.xlsx
|
|
|
|
done
|