diff --git a/backend/src/middlewares/upload.js b/backend/src/middlewares/upload.js index ea3e835..0a24ab3 100644 --- a/backend/src/middlewares/upload.js +++ b/backend/src/middlewares/upload.js @@ -1,11 +1,20 @@ const util = require('util'); const Multer = require('multer'); -const maxSize = 10 * 1024 * 1024; -let processFile = Multer({ - storage: Multer.memoryStorage(), - limits: { fileSize: maxSize }, -}).single("file"); +const DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024; -let processFileMiddleware = util.promisify(processFile); -module.exports = processFileMiddleware; +const createProcessFile = (maxFileSize = DEFAULT_MAX_FILE_SIZE) => { + const processFile = Multer({ + storage: Multer.memoryStorage(), + limits: { fileSize: maxFileSize }, + }).single('file'); + + return util.promisify(processFile); +}; + +const defaultProcessFile = createProcessFile(); + +defaultProcessFile.createProcessFile = createProcessFile; +defaultProcessFile.DEFAULT_MAX_FILE_SIZE = DEFAULT_MAX_FILE_SIZE; + +module.exports = defaultProcessFile; diff --git a/backend/src/routes/file.js b/backend/src/routes/file.js index ddd2bc0..b88de7a 100644 --- a/backend/src/routes/file.js +++ b/backend/src/routes/file.js @@ -1,29 +1,38 @@ const express = require('express'); -const config = require('../config'); -const path = require('path'); const passport = require('passport'); const services = require('../services/file'); const router = express.Router(); -router.get('/download', (req, res) => { - if (process.env.NODE_ENV == "production" || process.env.NEXT_PUBLIC_BACK_API) { - services.downloadGCloud(req, res); +const DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024; +const MEDIA_UPLOAD_MAX_FILE_SIZE = 512 * 1024 * 1024; + +const getMaxFileSize = (table, field) => { + if (table === 'media_assets' && field === 'file') { + return MEDIA_UPLOAD_MAX_FILE_SIZE; } - else { + + return DEFAULT_MAX_FILE_SIZE; +}; + +router.get('/download', (req, res) => { + if (process.env.NODE_ENV == 'production' || process.env.NEXT_PUBLIC_BACK_API) { + services.downloadGCloud(req, res); + } else { services.downloadLocal(req, res); } }); -router.post('/upload/:table/:field', passport.authenticate('jwt', {session: false}), (req, res) => { - const fileName = `${req.params.table}/${req.params.field}`; +router.post('/upload/:table/:field', passport.authenticate('jwt', { session: false }), (req, res) => { + const { table, field } = req.params; + const fileName = `${table}/${field}`; + const maxFileSize = getMaxFileSize(table, field); - if (process.env.NODE_ENV == "production" || process.env.NEXT_PUBLIC_BACK_API) { - services.uploadGCloud(fileName, req, res); - } - else { + if (process.env.NODE_ENV == 'production' || process.env.NEXT_PUBLIC_BACK_API) { + services.uploadGCloud(fileName, req, res, { maxFileSize }); + } else { services.uploadLocal(fileName, { entity: null, - maxFileSize: 10 * 1024 * 1024, + maxFileSize, folderIncludesAuthenticationUid: false, })(req, res); } diff --git a/backend/src/services/file.js b/backend/src/services/file.js index 597be30..0c03116 100644 --- a/backend/src/services/file.js +++ b/backend/src/services/file.js @@ -78,6 +78,11 @@ const uploadLocal = ( }); form.on('error', function (err) { + if (err && /maxFileSize|maxFieldsSize|maxTotalFileSize/i.test(err.message || '')) { + res.status(413).send({ message: 'File is too large for this upload.' }); + return; + } + res.status(500).send(err); }); } @@ -91,8 +96,11 @@ const downloadLocal = async (req, res) => { res.download(path.join(config.uploadDir, privateUrl)); } -const initGCloud = () => { - const processFile = require("../middlewares/upload"); +const initGCloud = (maxFileSize) => { + const defaultProcessFile = require('../middlewares/upload'); + const processFile = maxFileSize + ? defaultProcessFile.createProcessFile(maxFileSize) + : defaultProcessFile; const { Storage } = require("@google-cloud/storage"); const crypto = require('crypto') @@ -112,9 +120,10 @@ const initGCloud = () => { return {hash, bucket, processFile}; } -const uploadGCloud = async (folder, req, res) => { +const uploadGCloud = async (folder, req, res, options = {}) => { try { - const {hash, bucket, processFile} = initGCloud(); + const { maxFileSize } = options; + const {hash, bucket, processFile} = initGCloud(maxFileSize); await processFile(req, res); let buffer = await req.file.buffer; let filename = await req.body.filename; @@ -155,6 +164,11 @@ const uploadGCloud = async (folder, req, res) => { } catch (err) { console.log(err); + if (err && err.code === 'LIMIT_FILE_SIZE') { + res.status(413).send({ message: 'File is too large for this upload.' }); + return; + } + res.status(500).send({ message: `Could not upload the file. ${err}` });