-
-
Save tripzilch/ca327ee3f74716fe3528782c604bc196 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
very simple local PNG/SVG saving server by Piter Pasma | |
USAGE: | |
it needs a folder ./saved/ and ./saved/frames/ in the | |
folder where you're running the script. command line: | |
node save-server.js | |
there are no options, but you can easily modify the code | |
here's a sample save_frame function: | |
----- | |
PROJ_NAME = "dimensionless-void"; | |
function save_frame(ctx, n) { | |
ctx.canvas.toBlob(blob => { | |
const xhr = new XMLHttpRequest(); | |
xhr.onreadystatechange = () => { | |
if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) { | |
console.log(`OK SAVE ${n} -- ${xhr.responseText}`); | |
// optionally put call to render the next frame here | |
// or you can do location.reload or something | |
} | |
} | |
// note that the saving behaviour is different depending on whether you pass | |
// in the `frame` parameter. just try it out, or see the code below for how it works. | |
xhr.open('POST', `http://127.0.0.1:8080/save?desc=${PROJ_NAME}&frame=${n}`); | |
xhr.send(blob); // alternatively you can also use a local IP like 192.168.178.23:8080 | |
}); | |
} | |
*/ | |
var http = require('http'); | |
var fs = require('fs'); | |
function dateFormat (date, fstr, utc=false) { | |
// from https://stackoverflow.com/a/10647272 | |
utc = utc ? 'getUTC' : 'get'; | |
return fstr.replace (/%[YmdHMS]/g, function (m) { | |
switch (m) { | |
case '%Y': return date[utc + 'FullYear'] (); // no leading zeros required | |
case '%m': m = 1 + date[utc + 'Month'] (); break; | |
case '%d': m = date[utc + 'Date'] (); break; | |
case '%H': m = date[utc + 'Hours'] (); break; | |
case '%M': m = date[utc + 'Minutes'] (); break; | |
case '%S': m = date[utc + 'Seconds'] (); break; | |
default: return m.slice (1); // unknown code, remove % | |
} | |
// add leading zero if required | |
return ('0' + m).slice (-2); | |
}); | |
} | |
const clean = s => s.replace(/[^0-9A-Za-z]+/g, '-'); | |
console.log('START SERVER! OKAY'); | |
http.createServer(function (req, res) { | |
const url = new URL(req.url, `http://${req.headers.host}`); | |
const desc = url.searchParams.get('desc'); | |
const frame = url.searchParams.get('frame'); | |
if (url.pathname == '/save' && req.method === 'POST') { | |
const content_type = req.headers['content-type']; | |
console.log(`====== SAVE, content-type=${content_type}`); | |
const chunks = []; | |
req.on('data', data => {chunks.push(data); }); | |
req.on('end', () => { | |
let data = Buffer.concat(chunks); | |
console.log(`=== Received data, length=${data.length}`); | |
let ext = false; | |
if (content_type === 'image/png') { | |
ext = 'png'; | |
} else if (content_type === 'text/plain;charset=UTF-8') { | |
data = data.toString(); | |
const data_svg_header0 = 'data:image/svg+xml,'; | |
const data_svg_header1 = 'data:image/svg+xml;charset=utf-8,'; | |
// const data_png_header = 'data:image/png;base64,'; | |
if (data.startsWith(data_svg_header0)) { | |
data = data.substring(data_svg_header0.length); | |
data = decodeURIComponent(data); | |
ext = 'svg'; | |
} else if (data.startsWith(data_svg_header1)) { | |
data = data.substring(data_svg_header1.length); | |
data = decodeURIComponent(data); | |
ext = 'svg'; | |
} /*else if (data.startsWith(data_png_header)) { | |
data = data.substring(data_png_header.length); | |
data = atob(data); // this not work? | |
ext = 'png'; | |
}*/ | |
} | |
if (!ext) { | |
res.writeHead(200, {'Content-Type': 'text/html', 'Access-Control-Allow-Origin': '*'}); | |
console.log(`Unexpected data, content_type = ${content_type}`); | |
console.log(data.substr(0, 250)); | |
res.write("Error: Unexpected data."); | |
return res.end(); | |
} | |
const fn_desc = desc ? clean(desc) : 'untitled'; | |
const date = dateFormat(new Date(), '%Y-%m-%d-%H-%M-%S'); | |
let filename; | |
if (frame) { | |
filename = `./saved/frames/${fn_desc}-${clean(frame)}.${ext}`; | |
} else { | |
filename = `./saved/${fn_desc}-${date}.${ext}`; | |
} | |
fs.writeFile(filename, data, (err) => { | |
if (err) throw err; | |
console.log("File saved to " + filename); | |
res.writeHead(200, { | |
'Content-Type': 'text/html', | |
'Access-Control-Allow-Origin': '*' | |
}); | |
res.write(`OK! ${data.length} bytes written to ${filename}`); | |
return res.end(); | |
}); | |
}); | |
} else if (req.method === 'OPTIONS') { | |
console.log(`OPTIONS!`); | |
res.writeHead(204, { | |
'Content-Type': 'text/html', | |
'Access-Control-Allow-Origin': '*', | |
'Access-Control-Allow-Method': 'OPTIONS, POST', | |
'Access-Control-Allow-Headers': 'Content-Type' | |
}); | |
return res.end(); | |
} else { | |
console.log('REQ 404!', req); | |
res.writeHead(404, {'Content-Type': 'text/html', 'Access-Control-Allow-Origin': '*'}); | |
res.write('Error 404'); | |
return res.end(); | |
} | |
}).listen(8080); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment