You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
74 lines
2.2 KiB
JavaScript
74 lines
2.2 KiB
JavaScript
const router = require('express-promise-router')()
|
|
const db = require('../db')
|
|
const ensureAdmin = require('./middleware/ensureAdmin')
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const cacheRoot = path.join(__dirname, '../cache/images')
|
|
|
|
fs.promises.mkdir(cacheRoot, {recursive: true})
|
|
.catch(() => console.error("Could not create image cache dir: " + cacheRoot));
|
|
|
|
const memCache = {};
|
|
|
|
async function writeImageFile(uuid, size, data) {
|
|
if(size !== 'thumb' && size !== 'large')
|
|
throw new Error(`Unknown image size ${size}`);
|
|
|
|
await fs.promises.writeFile(path.join(cacheRoot, `${uuid}-${size}`), data);
|
|
}
|
|
|
|
async function getImage(uuid, size) {
|
|
// If we've already stored a mime type, that means we've written the file to disk
|
|
if(memCache[`${uuid}-${size}`]?.mime_type) {
|
|
return {
|
|
file: fs.createReadStream(path.join(cacheRoot, `${uuid}-${size}`)),
|
|
mime_type: memCache[`${uuid}-${size}`].mime_type
|
|
}
|
|
}
|
|
|
|
// If we've stored a promise, that means we're currently retrieving it from the db
|
|
if(memCache[`${uuid}-${size}`]?.dbPromise) {
|
|
return await memCache[`${uuid}-${size}`]?.dbPromise;
|
|
}
|
|
|
|
// Otherwise, retrieve it from the DB, and then write it to disk
|
|
const record = memCache[`${uuid}-${size}`] = {};
|
|
record.dbPromise = db.item.getImage(uuid, size);
|
|
|
|
const image = await record.dbPromise;
|
|
await writeImageFile(uuid, size, image.file);
|
|
|
|
record.mime_type = image.mime_type;
|
|
delete record.dbPromise;
|
|
|
|
return image;
|
|
}
|
|
|
|
router.get('/:uuid/:size', async (req, res) => {
|
|
const image = await getImage(req.params.uuid, req.params.size)
|
|
|
|
const cacheSeconds = 60 * 60 * 24;
|
|
res.set('Cache-Control', cacheSeconds);
|
|
res.set('Content-Type', image.mime_type)
|
|
|
|
if(Buffer.isBuffer(image.file))
|
|
res.end(image.file)
|
|
else if (typeof image.file.pipe === 'function')
|
|
image.file.pipe(res)
|
|
else
|
|
throw new Error("Unable to send file to user");
|
|
})
|
|
|
|
router.post('/:uuid/featured', ensureAdmin, async (req, res) => {
|
|
const item = await db.item.setFeatured(req.params.uuid)
|
|
res.json(item)
|
|
})
|
|
|
|
router.delete('/:uuid', ensureAdmin, async (req, res) => {
|
|
const item = await db.item.removeImage(req.params.uuid)
|
|
res.json(item)
|
|
})
|
|
|
|
module.exports = router
|