const fs = require('fs'); const path = require('path'); const express = require('express'); const sanitize = require('sanitize-filename'); const { jsonParser } = require('../express-common'); const { clientRelativePath, removeFileExtension, getImages } = require('../util'); /** * Ensure the directory for the provided file path exists. * If not, it will recursively create the directory. * * @param {string} filePath - The full path of the file for which the directory should be ensured. */ function ensureDirectoryExistence(filePath) { const dirname = path.dirname(filePath); if (fs.existsSync(dirname)) { return true; } ensureDirectoryExistence(dirname); fs.mkdirSync(dirname); } const router = express.Router(); /** * Endpoint to handle image uploads. * The image should be provided in the request body in base64 format. * Optionally, a character name can be provided to save the image in a sub-folder. * * @route POST /api/images/upload * @param {Object} request.body - The request payload. * @param {string} request.body.image - The base64 encoded image data. * @param {string} [request.body.ch_name] - Optional character name to determine the sub-directory. * @returns {Object} response - The response object containing the path where the image was saved. */ router.post('/upload', jsonParser, async (request, response) => { // Check for image data if (!request.body || !request.body.image) { return response.status(400).send({ error: 'No image data provided' }); } try { // Extracting the base64 data and the image format const splitParts = request.body.image.split(','); const format = splitParts[0].split(';')[0].split('/')[1]; const base64Data = splitParts[1]; const validFormat = ['png', 'jpg', 'webp', 'jpeg', 'gif'].includes(format); if (!validFormat) { return response.status(400).send({ error: 'Invalid image format' }); } // Constructing filename and path let filename; if (request.body.filename) { filename = `${removeFileExtension(request.body.filename)}.${format}`; } else { filename = `${Date.now()}.${format}`; } // if character is defined, save to a sub folder for that character let pathToNewFile = path.join(request.user.directories.userImages, sanitize(filename)); if (request.body.ch_name) { pathToNewFile = path.join(request.user.directories.userImages, sanitize(request.body.ch_name), sanitize(filename)); } ensureDirectoryExistence(pathToNewFile); const imageBuffer = Buffer.from(base64Data, 'base64'); await fs.promises.writeFile(pathToNewFile, imageBuffer); response.send({ path: clientRelativePath(request.user.directories.root, pathToNewFile) }); } catch (error) { console.log(error); response.status(500).send({ error: 'Failed to save the image' }); } }); router.post('/list/:folder', (request, response) => { const directoryPath = path.join(request.user.directories.userImages, sanitize(request.params.folder)); if (!fs.existsSync(directoryPath)) { fs.mkdirSync(directoryPath, { recursive: true }); } try { const images = getImages(directoryPath); return response.send(images); } catch (error) { console.error(error); return response.status(500).send({ error: 'Unable to retrieve files' }); } }); module.exports = { router };