You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
140 lines
3.9 KiB
140 lines
3.9 KiB
// page.js
|
|
// Copyright (C) 2022 DTP Technologies, LLC
|
|
// License: Apache-2.0
|
|
|
|
'use strict';
|
|
|
|
const fs = require('fs');
|
|
|
|
const express = require('express');
|
|
const mongoose = require('mongoose');
|
|
const multer = require('multer');
|
|
|
|
const { SiteController/*, SiteError*/ } = require('../../lib/site-lib');
|
|
|
|
class ImageController extends SiteController {
|
|
|
|
constructor (dtp) {
|
|
super(dtp, module.exports);
|
|
|
|
}
|
|
|
|
async start ( ) {
|
|
const { dtp } = this;
|
|
const { limiter: limiterService } = dtp.services;
|
|
|
|
const router = express.Router();
|
|
dtp.app.use('/image', router);
|
|
|
|
const imageUpload = multer({
|
|
dest: `/tmp/${this.dtp.config.site.domainKey}/uploads/${this.component.slug}`,
|
|
limits: {
|
|
fileSize: 1024 * 1000 * 12,
|
|
},
|
|
});
|
|
|
|
router.use(async (req, res, next) => {
|
|
res.locals.currentView = 'image';
|
|
return next();
|
|
});
|
|
|
|
router.param('imageId', this.populateImage.bind(this));
|
|
|
|
router.post('/tinymce',
|
|
imageUpload.single('file'),
|
|
this.postTinyMceImage.bind(this),
|
|
);
|
|
|
|
router.post('/',
|
|
limiterService.createMiddleware(limiterService.config.image.postCreateImage),
|
|
imageUpload.single('file'),
|
|
this.postCreateImage.bind(this),
|
|
);
|
|
|
|
router.get('/:imageId',
|
|
limiterService.createMiddleware(limiterService.config.image.getImage),
|
|
this.getHostCacheImage.bind(this),
|
|
// this.getImage.bind(this),
|
|
);
|
|
}
|
|
|
|
async populateImage (req, res, next, imageId) {
|
|
try {
|
|
res.locals.imageId = mongoose.Types.ObjectId(imageId);
|
|
res.locals.image = await this.dtp.services.image.getImageById(res.locals.imageId);
|
|
return next();
|
|
} catch (error) {
|
|
this.log.error('failed to populate image', { error });
|
|
return next(error);
|
|
}
|
|
}
|
|
|
|
async postTinyMceImage (req, res, next) {
|
|
const { image: imageService } = this.dtp.services;
|
|
try {
|
|
res.locals.image = await imageService.create(req.user, req.body, req.file);
|
|
res.status(200).json({ location: `/image/${res.locals.image._id}` });
|
|
} catch (error) {
|
|
this.log.error('failed to create image', { error });
|
|
return next(error);
|
|
}
|
|
}
|
|
|
|
async postCreateImage (req, res, next) {
|
|
const { image: imageService } = this.dtp.services;
|
|
try {
|
|
res.locals.image = await imageService.create(req.user, req.body, req.file);
|
|
res.status(200).json({
|
|
success: true,
|
|
imageId: res.locals.image._id.toString(),
|
|
});
|
|
} catch (error) {
|
|
this.log.error('failed to create image', { error });
|
|
return next(error);
|
|
}
|
|
}
|
|
|
|
async getHostCacheImage (req, res) {
|
|
const { hostCache: hostCacheService } = this.dtp.services;
|
|
const { image } = res.locals;
|
|
try {
|
|
const fileInfo = await hostCacheService.getFile(image.file.bucket, image.file.key);
|
|
const stream = fs.createReadStream(fileInfo.file.path);
|
|
res.header('Content-Type', image.type);
|
|
res.header('Content-Length', fileInfo.file.stats.size);
|
|
res.status(200);
|
|
stream.pipe(res);
|
|
} catch (error) {
|
|
this.log.error('failed to fetch image', { image, error });
|
|
return res.status(error.statusCode || 500).json({
|
|
success: false,
|
|
message: error.message,
|
|
});
|
|
}
|
|
}
|
|
|
|
async getImage (req, res) {
|
|
const { minio: minioService } = this.dtp.services;
|
|
try {
|
|
const stream = await minioService.openDownloadStream({
|
|
bucket: res.locals.image.file.bucket,
|
|
key: res.locals.image.file.key
|
|
});
|
|
res.header('Content-Type', res.locals.image.type);
|
|
res.header('Content-Length', res.locals.image.size);
|
|
res.status(200);
|
|
stream.pipe(res);
|
|
} catch (error) {
|
|
return res.status(error.statusCode || 500).json({
|
|
success: false,
|
|
message: error.message,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
slug: 'image',
|
|
name: 'image',
|
|
create: async (dtp) => { return new ImageController(dtp); },
|
|
};
|
|
|