diff --git a/index.js b/index.js index 2890d97..bedc496 100644 --- a/index.js +++ b/index.js @@ -183,6 +183,52 @@ async function saveFile(structureId, req, uploadedFile, asset = false) { return file; } +async function saveData(structureId, req, fileData, asset = false) { + const name = fileData.name; + let mimetype = fileData.mimetype || "application/octet-stream"; + let data = fileData.data; + + if (typeof data === "string") { + const dataUrl = data.match(/^data:([^;,]+);base64,([\s\S]+)$/); + if (dataUrl) { + mimetype = fileData.mimetype || dataUrl[1]; + data = Buffer.from(dataUrl[2].replace(/\s/g, ""), "base64"); + } else { + data = Buffer.from(data.replace(/\s/g, ""), fileData.encoding || "base64"); + } + } else if (data instanceof ArrayBuffer) { + data = Buffer.from(data); + } else if (ArrayBuffer.isView(data)) { + data = Buffer.from(data.buffer, data.byteOffset, data.byteLength); + } + + if (!Buffer.isBuffer(data)) { + throw new Error("files.saveData requires base64, ArrayBuffer, Uint8Array, or Buffer data"); + } + + const [mime_type, mime_subtype] = mimetype.split("/"); + const sid = String(structureId); + const uploadPath = path.join(__dirname, "public", sid); + const storedPath = path.join(sid, name); + + fs.mkdirSync(uploadPath, { recursive: true }); + await fs.promises.writeFile(path.join(uploadPath, name), data); + + let id = model.createFile( + structureId, + name, + storedPath, + mime_type, + mime_subtype, + asset, + ); + + let file = model.getFile(id); + file.url = prefixUrlWithHost(req, file.path); + + return file; +} + // A console whose log() mirrors to stdout and to the structure's logs table. function makeConsole(structureId, routeId) { return { @@ -238,7 +284,10 @@ function makeLibs(structureId, console, memberUserId) { }, push: push, notifications: makeNotifications(structureId, memberUserId), - files: { saveFile: (...args) => saveFile(structureId, ...args) }, + files: { + saveFile: (...args) => saveFile(structureId, ...args), + saveData: (...args) => saveData(structureId, ...args), + }, }; }