import fs, {copyFileSync, mkdirSync, statSync} from 'fs'; import {join, extname} from 'path'; import multer from 'multer'; import sharp from 'sharp'; import {uid} from 'rand-token'; import Pages from './Pages'; import {getBaseUrl} from '../helpers'; import {pagination} from '../config'; const checkAndCreateDirectory = async (directory) => { try { return statSync(directory); } catch (err) { if (err.errno === -2) { mkdirSync(directory); } else { throw err; } } return true; }; const resizeImage = async (sourceImage, destImage, w, h) => { return sharp(sourceImage) .resize(w, h, { fit: 'inside', }) .toFile(destImage); }; /** * Classe permettant la gestion des images */ class Uploads extends Pages { /** * @param {Object} req * @param {String} viewname */ constructor(req, viewname) { super(req, viewname); this.upload = multer({ storage: multer.diskStorage({}), fileFilter(multerReq, file, cb) { const filetypes = /jpeg|jpg|png/; const mimetype = filetypes.test(file.mimetype); const filExtname = filetypes.test( extname(file.originalname).toLowerCase(), ); if (mimetype && filExtname) { return cb(null, true); } const error = 'Seuls les fichiers de type jpg et png sont acceptés'; req.session.messages.push(error); return cb(new Error(error)); }, }).single('image'); const baseUrl = getBaseUrl(req); this.baseUploadDir = `${__dirname}/../../uploads/`; this.userUploadDir = join(this.baseUploadDir, req.user._id); this.userUri = `${baseUrl}/uploads/${req.user._id}`; } /** * * @param {*} req * @param {*} callback */ async postOne(req) { await new Promise((resolve, reject) => { this.upload(req, req.body, (err, data) => { if (err) { return reject(err); } resolve(data); }); }); checkAndCreateDirectory(this.baseUploadDir); checkAndCreateDirectory(this.userUploadDir); let ext = req.file.originalname.split('.'); ext = ext[ext.length - 1]; // eslint-disable-next-line max-len const uploadname = `${uid(4)}_${Buffer.from(req.file.originalname).toString('base64')}.${ext}`; const originalFileName = uploadname; const mediumFileName = `medium_${uploadname}`; const smallFileName = `small_${uploadname}`; copyFileSync(req.file.path, join(this.userUploadDir, originalFileName)); await resizeImage( req.file.path, path.join( this.userUploadDir, mediumFileName, ), 800, 600, ); await resizeImage( req.file.path, path.join( this.userUploadDir, smallFileName, ), 300, 200, ); this.pageContent.page.upload = { originalFile: `${this.userUri}/${originalFileName}`, mediumFile: `${this.userUri}/${mediumFileName}`, smallFile: `${this.userUri}/${smallFileName}`, }; return true; } /** * Méthode permettant d'afficher la liste des images d'un utilisateur * @param {Object} req */ async getAll(req) { const currentPage = Number(req.query.page || 1); const startAt = (currentPage - 1) * pagination; const endAt = startAt + pagination; const listOfFiles = []; let total = 0; checkAndCreateDirectory(this.baseUploadDir); checkAndCreateDirectory(this.userUploadDir); const files = fs.readdirSync(this.userUploadDir) .map((v) => { // eslint-disable-next-line max-len return {name: v, time: statSync(join(this.userUploadDir, v)).mtime.getTime()}; }) .sort(function(a, b) { return b.time - a.time; }) .map(function(v) { return v.name; }); for (let i = 0; i < files.length; i += 1) { const file = files[i]; if (file.indexOf('medium_') === 0) { total += 1; if (listOfFiles.length < endAt) { listOfFiles.push({ originalFile: `${this.userUri}/${file.replace('medium_', '')}`, mediumFile: `${this.userUri}/${file}`, smallFile: `${this.userUri}/${file.replace('medium_', 'small_')}`, }); } } } this.pageContent.page.images = listOfFiles.slice(startAt); this.pageContent.page.currentPage = currentPage; // eslint-disable-next-line max-len this.pageContent.page.totalPages = Math.floor(total / pagination) + (total % pagination > 0 ? 1 : 0); } } module.exports = Uploads;