const express = require('express') const router = express.Router() const async = require('async') const path = require('path') const multer = require('multer') const fs = require('fs-extra') const upload = multer({ dest: 'uploads' }) const sharp = require('sharp') const TOL = require('../../tools/common') const CFG = require('../../config') var CTX = null module.exports = function (pCtx) { CTX = pCtx router.post('/upload', upload.single('media'), handleUploadedMedia) router.get('/get/:id', function (req, res) { let mediaId = req.params.id CTX.restapi.media.__services.readOne(mediaId, {projection: {path: 1}}, function (pErr, pResult) { if (pErr) { return res.status(404).send('Media:Media:NotFound') } let mediaPath = path.join(CFG.media.documents, pResult.data.path) fs.access(mediaPath, fs.constants.F_OK, function (pErr) { if (pErr) { return res.status(404).send('Media:File:NotFound') } res.sendFile(mediaPath) }) }) }) router.get('/preview/:id', function (req, res) { let mediaId = req.params.id CTX.restapi.media.__services.readOne(mediaId, {projection: {mimetype: 1, path: 1}}, function (pErr, pResult) { if (pErr) { return res.sendFile(CFG.media['404']) } let media = pResult.data let mimetypes = media.mimetype.split('/') let type = mimetypes[0] let subtype = mimetypes[1] switch (type) { case 'image': let mediaPath = path.join(CFG.media.documents, media.path) getPreviewFromImage(res, mediaPath, req.query) break default: res.sendFile(CFG.media['404']) } }) }) return router } function getPreviewFromImage (res, pPath, pQuery, pMedia) { let query = pQuery query.width = parseInt(query.width) || null query.height = parseInt(query.height) || null query.fit = query.fit || 'cover' if (!query.width && !query.height) { query.width = 1024 } let outName = TOL.createHash(JSON.stringify(query), 'sha1') let outPath = path.join(CFG.media.cache, generatePathFromMediaId(outName)) let outFull = path.join(outPath, `${outName}.jpg`) let tasks = [] tasks.push(function (pCb) { fs.ensureDir(outPath, pErr => pCb(pErr)) }) tasks.push(function (pCb) { sharp(pPath) .resize(query.width, query.height, {fit: query.fit}) .toFile(outFull, function (pErr) { pCb(pErr) }) }) async.waterfall(tasks, function (pErr) { if (pErr) { console.log(pErr) res.sendFile(CFG.media['404']) } else { res.sendFile(outFull) } }) } function handleUploadedMedia (req, res) { let tasks = [] let file = req.file let fileKey = { coll: '__default', id: '', path: '' } let ext = getExtensionFromMimetype(file.mimetype) let currentDate = new Date() if (req.body.docColl && req.body.docId && req.body.docPath) { fileKey = { coll: req.body.docColl, id: req.body.docId, path: req.body.docPath } } let mediaId = TOL.createHash(JSON.stringify(fileKey.coll === '__default' ? file : fileKey), 'sha1') let outPath = path.join(CFG.media.documents, generatePathFromMediaId(mediaId)) let outName = `media.${ext}` let outFull = path.join(outPath, outName) let isAlreadyExisting = false file.createdAt = currentDate file.fileKey = fileKey tasks.push(function (pCb) { fs.ensureDir(outPath, pErr => pCb(pErr)) }) tasks.push(function (pCb) { fs.move(file.path, outFull, { overwrite: true }, pErr => pCb(pErr)) }) tasks.push(function (pCb) { fs.writeFile(path.join(outPath, 'info'), JSON.stringify(file, null, 2), 'utf8', pErr => pCb(pErr)) }) tasks.push(function (pCb) { CTX.restapi.media.__services.readOne(mediaId, {projection: {_id: 1}}, function (pErr, pResult) { if (pResult && pResult.ok) { isAlreadyExisting = true } pCb() }) }) tasks.push(function (pCb) { let doc = { _id: mediaId, name: outName, originalName: file.originalname, extension: ext, path: path.join(generatePathFromMediaId(mediaId), outName), fileKey: fileKey, mimetype: file.mimetype, size: file.size } if (isAlreadyExisting) { CTX.restapi.media.__services.update(mediaId, doc, req.user, 'media', function (pErr, pResult) { pCb(pErr) }) } else { CTX.restapi.media.__services.create(doc, req.user, function (pErr, pResult) { pCb(pErr) }) } }) async.waterfall(tasks, function (pErr) { res.done(pErr, { ok: pErr ? 0 : 1, mediaId: mediaId }) }) } function generatePathFromMediaId (pMediaId) { let outSubf = pMediaId.slice(0, 4) return path.join(outSubf, pMediaId) } function getExtensionFromMimetype (pMimetype) { let ext = 'unknown' let mimetypes = pMimetype.split('/') let type = mimetypes[0] let subtype = mimetypes[1] switch (type) { case 'audio': case 'video': case 'image': ext = subtype break case 'application/pdf': ext = 'pdf' break default: } return ext }