const formidable = require('formidable'); const fs = require('fs'); const config = require('../config'); const path = require('path'); const { format } = require("util"); const ensureDirectoryExistence = (filePath) => { const dirname = path.dirname(filePath); if (fs.existsSync(dirname)) { return true; } ensureDirectoryExistence(dirname); fs.mkdirSync(dirname); } const uploadLocal = ( folder, validations = { entity: null, maxFileSize: null, folderIncludesAuthenticationUid: false, }, ) => { return (req, res) => { if (!req.currentUser) { res.sendStatus(403); return; } if ( validations.entity ) { res.sendStatus(403); return; } if (validations.folderIncludesAuthenticationUid) { folder = folder.replace( ':userId', req.currentUser.authenticationUid, ); if ( !req.currentUser.authenticationUid || !folder.includes(req.currentUser.authenticationUid) ) { res.sendStatus(403); return; } } const form = new formidable.IncomingForm(); form.uploadDir = config.uploadDir; if (validations && validations.maxFileSize) { form.maxFileSize = validations.maxFileSize; } form.parse(req, function (err, fields, files) { const filename = String(fields.filename); const fileTempUrl = files.file.path; if (!filename) { fs.unlinkSync(fileTempUrl); res.sendStatus(500); return; } const privateUrl = path.join( form.uploadDir, folder, filename, ); ensureDirectoryExistence(privateUrl); fs.renameSync(fileTempUrl, privateUrl); res.sendStatus(200); }); form.on('error', function (err) { res.status(500).send(err); }); } } const downloadLocal = async (req, res) => { const privateUrl = req.query.privateUrl; if (!privateUrl) { return res.sendStatus(404); } res.download(path.join(config.uploadDir, privateUrl)); } const initGCloud = () => { const processFile = require("../middlewares/upload"); const { Storage } = require("@google-cloud/storage"); const crypto = require('crypto') const hash = config.gcloud.hash const privateKey = process.env.GC_PRIVATE_KEY.replace(/\\\n/g, "\n"); const storage = new Storage({ projectId: process.env.GC_PROJECT_ID, credentials: { client_email: process.env.GC_CLIENT_EMAIL, private_key: privateKey } }); const bucket = storage.bucket(config.gcloud.bucket); return {hash, bucket, processFile}; } const uploadGCloud = async (folder, req, res) => { try { const {hash, bucket, processFile} = initGCloud(); await processFile(req, res); let buffer = await req.file.buffer; let filename = await req.body.filename; if (!req.file) { return res.status(400).send({ message: "Please upload a file!" }); } let path = `${hash}/${folder}/${filename}`; let blob = bucket.file(path); console.log(path); const blobStream = blob.createWriteStream({ resumable: false, }); blobStream.on("error", (err) => { console.log('Upload error'); console.log(err.message); res.status(500).send({ message: err.message }); }); console.log(`https://storage.googleapis.com/${bucket.name}/${blob.name}`); blobStream.on("finish", async (data) => { const publicUrl = format( `https://storage.googleapis.com/${bucket.name}/${blob.name}` ); res.status(200).send({ message: "Uploaded the file successfully: " + path, url: publicUrl, }); }); blobStream.end(buffer) } catch (err) { console.log(err); res.status(500).send({ message: `Could not upload the file. ${err}` }); } } const downloadGCloud = async (req, res) => { try { const {hash, bucket, processFile} = initGCloud(); const privateUrl = await req.query.privateUrl; const filePath = `${hash}/${privateUrl}`; const file = bucket.file(filePath) const fileExists = await file.exists(); if (fileExists[0]) { const stream = file.createReadStream(); stream.pipe(res); } else { res.status(404).send({ message: "Could not download the file. " + err, }); } } catch (err) { res.status(404).send({ message: "Could not download the file. " + err, }); } } const deleteGCloud = async (privateUrl) => { try { const {hash, bucket, processFile} = initGCloud(); const filePath = `${hash}/${privateUrl}`; const file = bucket.file(filePath) const fileExists = await file.exists(); if (fileExists[0]) { file.delete(); } } catch (err) { console.log(`Cannot find the file ${privateUrl}`); } } module.exports = { initGCloud, uploadLocal, downloadLocal, deleteGCloud, uploadGCloud, downloadGCloud }