From 2e353cdba464b2427c948348e760dc95f92513e1 Mon Sep 17 00:00:00 2001 From: SheetJS Date: Sun, 9 Aug 2020 01:04:31 -0400 Subject: [PATCH] process uploads --- api/data/index.js | 37 ++++++++++++------------------------- api/upload/index.js | 28 ++++++++++++++++++++++++++++ package.json | 2 +- public/index.html | 34 ++++++++++++++++++++++++++++------ src/util.js | 33 +++++++++++++++++++++++++++++++++ 5 files changed, 102 insertions(+), 32 deletions(-) create mode 100644 api/upload/index.js create mode 100644 src/util.js diff --git a/api/data/index.js b/api/data/index.js index fc60e1d..40c9d47 100644 --- a/api/data/index.js +++ b/api/data/index.js @@ -1,36 +1,23 @@ -const XLSX = require('xlsx'); const URL = require('url'); +const do_wb = require('../../src/util'); const request = require('request'); -const do_url = (req, url, res) => { +module.exports = function(req, res) { + res.setHeader('Access-Control-Allow-Origin', '*'); + const url = URL.parse(req.url, true); + + /* request url and process */ + if(!url.query.url) return res.status(400).send("Must specify url"); request(url.query.url, {encoding:null}, function(err, response, body) { - if(err) return res.status(500).send(err.toString()); + if(err) return res.status(502).send(err.toString()); + + /* response.statusCode is expected to be 200 */ switch(response.statusCode) { case 200: break; case 404: return res.status(404).send(`Cannot find ${url.query.url}`); default: return res.status(500).send(`Unrecognized status code ${response.statusCode}`); } - const wb = XLSX.read(body, {type:'buffer'}); - const N = url.query.N ? parseInt(url.query.N,10) : 0; - if(N < 0) { - switch(url.query.t || "csv") { - case "json": return res.status(200).send(JSON.stringify(wb.SheetNames.join("\n"))); - default: return res.status(200).send(wb.SheetNames.join("\n")); - } - } - if(N >= wb.SheetNames.length) return res.status(500).send(`Cannot find sheet ${N}`); - var ws = wb.Sheets[wb.SheetNames[N]]; - switch(url.query.t) { - case "json": return res.status(200).json(XLSX.utils.sheet_to_json(ws, {header:1, raw:true})); - case "html": return XLSX.stream.to_html(ws).pipe(res); - default: XLSX.stream.to_csv(ws).pipe(res); - } + + do_wb(req, body, url, res); }); }; - -module.exports = function(req, res) { - var url = URL.parse(req.url, true); - res.setHeader('Access-Control-Allow-Origin', '*'); - if(!url.query.url) return res.status(500).send("Must issue command"); - do_url(req, url, res); -}; diff --git a/api/upload/index.js b/api/upload/index.js new file mode 100644 index 0000000..724781b --- /dev/null +++ b/api/upload/index.js @@ -0,0 +1,28 @@ +const URL = require('url'), fs = require('fs'); +const do_wb = require('../../src/util'); +const formidable = require('formidable-serverless'); + +module.exports = function(req, res) { + res.setHeader('Access-Control-Allow-Origin', '*'); + const url = URL.parse(req.url, true); + + /* parse form data */ + const form = formidable({multiples: true, maxFileSize: 2*1024*1024}); + form.parse(req, (err, fields, files) => { + if(err) return res.status(400).send(err.message || err); + if(!url.query) url.query = fields; + ["N", "t"].forEach(k => { if(!url.query[k] && fields[k] != null) url.query[k] = fields[k]; }); + + /* look for first uploaded file entry */ + if(!files) return res.status(400).send("Missing file"); + const fentries = Object.entries(files); + if(fentries.length == 0) return res.status(400).send("Missing file"); + + /* read file */ + const file = fentries[0][1]; + fs.readFile(file.path, (err, body) => { + if(err) return res.status(500).send(err.message || err); + do_wb(req, body, url, res); + }); + }); +}; diff --git a/package.json b/package.json index e9a5d92..949e802 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "description": "Spreadsheet CSV conversion microservice", "keywords": ["csv", "spreadsheet", "data", "conversion", "excel"], "dependencies": { - "micro":"", + "formidable-serverless":"", "request":"", "xlsx":"" }, diff --git a/public/index.html b/public/index.html index cccd588..13ee3af 100644 --- a/public/index.html +++ b/public/index.html @@ -8,7 +8,7 @@
 SheetJS Spreadsheet Conversion Service
 
-send a request to /api/data?url=<url>&N=<idx> to convert the spreadsheet at `url` to a simpler format
+Proxy: send a request to /api/data to convert the spreadsheet at `url` to a simpler format
 
 parameters:
 - url=<url>      the url to request
@@ -28,12 +28,12 @@ var URLS = [
 	[],
 	["[LIST]", {url:URL2,N:-1}],
 	["[N=1] ", {url:URL2,N:1}],
-	["[N=2] ", {url:URL2,N:2}],
-	["[N=3] ", {url:URL2,N:3}],
+//	["[N=2] ", {url:URL2,N:2}],
+//	["[N=3] ", {url:URL2,N:3}],
 	["[N=4] ", {url:URL2,N:4}],
-	["[N=5] ", {url:URL2,N:5}],
-	["[N=6] ", {url:URL2,N:6}],
-	["[N=7] ", {url:URL2,N:7}],
+//	["[N=5] ", {url:URL2,N:5}],
+//	["[N=6] ", {url:URL2,N:6}],
+//	["[N=7] ", {url:URL2,N:7}],
 	["[N=8] ", {url:URL2,N:8}]
 ];
 var parms = ["N", "t"];
@@ -45,6 +45,28 @@ for(var i = 0; i < URLS.length; ++i) {
 }
 
 
+
+Upload: upload a file to /api/upload to convert the spreadsheet at `url` to a simpler format
+
+parameters:
+- N=<idx>        the sheet index to use (-1 returns a list of sheet names in the workbook)
+- t=<type>       export type: "json" for json, "html" for html, default is CSV
+
+example:
+
+ + + + + + + +
+ This service is powered by SheetJS Source Code: diff --git a/src/util.js b/src/util.js new file mode 100644 index 0000000..37d0f11 --- /dev/null +++ b/src/util.js @@ -0,0 +1,33 @@ +const XLSX = require('xlsx'); + +module.exports = function(req, body, url, res) { + /* try to read the buffer */ + let wb; + try { + wb = XLSX.read(body, {type:'buffer'}); + } catch(e) { return res.status(500).send(e.message || e); } + + /* N parameter specifies worksheet index */ + const N = url.query.N ? parseInt(url.query.N,10) : 0; + + /* -1 -> return sheet names */ + if(N < 0) switch(url.query.t || "csv") { + case "json": return res.status(200).send(JSON.stringify(wb.SheetNames.join("\n"))); + default: return res.status(200).send(wb.SheetNames.join("\n")); + } + + /* find worksheet */ + if(N >= wb.SheetNames.length) return res.status(500).send(`Cannot find sheet ${N}`); + const ws = wb.Sheets[wb.SheetNames[N]]; + + /* result depends on "t" parameter: + * - json: AOA (sheet_to_json with header:1, raw: true) + * - html: HTML (using stream.to_html) + * default: CSV (using stream.to_csv) + */ + switch(url.query.t) { + case "json": return res.status(200).json(XLSX.utils.sheet_to_json(ws, {header:1, raw:true})); + case "html": return XLSX.stream.to_html(ws).pipe(res); + default: return XLSX.stream.to_csv(ws).pipe(res); + } +};