WIP - merges media storage
This commit is contained in:
14
.vscode/launch.json
vendored
Normal file
14
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Launch Program",
|
||||
"program": "${workspaceFolder}/demo/init.js"
|
||||
}
|
||||
]
|
||||
}
|
||||
69
src/controllers/media.controller.js
Normal file
69
src/controllers/media.controller.js
Normal file
@@ -0,0 +1,69 @@
|
||||
import mkdirp from 'mkdirp';
|
||||
import { resizeAndSave } from '../utils/imageResizer';
|
||||
import httpStatus from 'http-status';
|
||||
import modelById from '../resolvers/modelById';
|
||||
|
||||
export async function update(req, res, next, config) {
|
||||
req.model.setDefaultLocale(req.locale);
|
||||
|
||||
let doc = await modelById(req, { returnRawDoc: true });
|
||||
if (!doc)
|
||||
return res.status(httpStatus.NOT_FOUND).send('Not Found');
|
||||
|
||||
Object.keys(req.body).forEach(e => {
|
||||
doc[e] = req.body[e];
|
||||
});
|
||||
|
||||
if (req.files && req.files.file) {
|
||||
doc['filename'] = req.files.file.name;
|
||||
let outputFilepath = `${config.staticDir}/${req.files.file.name}`;
|
||||
let moveError = await req.files.file.mv(outputFilepath);
|
||||
if (moveError) return res.status(500).send(moveError);
|
||||
doc['sizes'] = await resizeAndSave(config, req.files.file);
|
||||
}
|
||||
|
||||
doc.save((saveError) => {
|
||||
if (saveError)
|
||||
return res.status(httpStatus.INTERNAL_SERVER_ERROR).json({ error: saveError });
|
||||
|
||||
return res.json({
|
||||
message: 'success',
|
||||
result: doc.toJSON({ virtuals: true })
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export async function upload(req, res, next, config) {
|
||||
if (!req.files || Object.keys(req.files).length === 0) {
|
||||
return res.status(400).send('No files were uploaded.');
|
||||
}
|
||||
|
||||
mkdirp(config.staticDir, (err) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
res.status(500).send('Upload failed.');
|
||||
}
|
||||
});
|
||||
|
||||
let outputFilepath = `${config.staticDir}/${req.files.file.name}`;
|
||||
let moveError = await req.files.file.mv(outputFilepath);
|
||||
if (moveError) return res.status(500).send(moveError);
|
||||
let outputSizes = await resizeAndSave(config, req.files.file);
|
||||
|
||||
req.model.create({
|
||||
name: req.body.name,
|
||||
caption: req.body.caption,
|
||||
description: req.body.description,
|
||||
filename: req.files.file.name,
|
||||
sizes: outputSizes
|
||||
}, (mediaCreateError, result) => {
|
||||
if (mediaCreateError)
|
||||
return res.status(500).json({ error: mediaCreateError });
|
||||
|
||||
return res.status(201)
|
||||
.json({
|
||||
message: 'success',
|
||||
result: result.toJSON({ virtuals: true })
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
import mkdirp from 'mkdirp';
|
||||
import { resize } from '../../src/utils/imageResizer';
|
||||
import Media from '../models/Media.model';
|
||||
|
||||
function upload(req, res, next, config) {
|
||||
if (Object.keys(req.files).length === 0) {
|
||||
return res.status(400).send('No files were uploaded.');
|
||||
}
|
||||
|
||||
mkdirp(config.staticDir, (err) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
res.status(500).send('Upload failed.');
|
||||
}
|
||||
});
|
||||
|
||||
let outputFilepath = `${config.staticDir}/${req.files.file.name}`;
|
||||
req.files.file.mv(outputFilepath, (err) => {
|
||||
if (err) return res.status(500).send(err);
|
||||
|
||||
if (req.files.file.mimetype.split('/')[0] === 'image') {
|
||||
resize(config, req.files.file);
|
||||
}
|
||||
|
||||
Media.create({
|
||||
name: req.files.file.name,
|
||||
filename: req.files.file.name
|
||||
}, (err, result) => {
|
||||
if (err)
|
||||
return res.status(500).json({ error: err });
|
||||
|
||||
return res.status(201)
|
||||
.json({
|
||||
message: 'success',
|
||||
result: {
|
||||
id: result.id,
|
||||
name: result.name
|
||||
}
|
||||
});
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
export default { upload };
|
||||
@@ -1,15 +1,28 @@
|
||||
import mongoose from 'mongoose';
|
||||
import buildQuery from '../plugins/buildQuery';
|
||||
import paginate from '../plugins/paginate';
|
||||
import internationalization from '../plugins/internationalization';
|
||||
|
||||
const MediaSchema = new mongoose.Schema({
|
||||
name: { type: String },
|
||||
caption: { type: String },
|
||||
description: { type: String },
|
||||
const mediaModelLoader = (config) => {
|
||||
const MediaSchema = new mongoose.Schema({
|
||||
name: { type: String, intl: true },
|
||||
caption: { type: String, intl: true },
|
||||
description: { type: String, intl: true },
|
||||
filename: { type: String },
|
||||
});
|
||||
sizes: [{
|
||||
height: { type: Number},
|
||||
width: { type: Number},
|
||||
_id: false
|
||||
}]
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
MediaSchema.plugin(paginate);
|
||||
MediaSchema.plugin(buildQuery);
|
||||
MediaSchema.plugin(paginate);
|
||||
MediaSchema.plugin(buildQuery);
|
||||
MediaSchema.plugin(internationalization, config.localization);
|
||||
|
||||
export default mongoose.model('Media', MediaSchema);
|
||||
return mongoose.model('Media', MediaSchema);
|
||||
};
|
||||
|
||||
export default mediaModelLoader;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import httpStatus from 'http-status';
|
||||
import { modelById } from '../resolvers';
|
||||
import {createAutopopulateOptions} from '../helpers/mongoose/createAutopopulateOptions';
|
||||
import { createAutopopulateOptions } from '../helpers/mongoose/createAutopopulateOptions';
|
||||
|
||||
const findOne = (req, res) => {
|
||||
|
||||
@@ -10,7 +10,7 @@ const findOne = (req, res) => {
|
||||
locale: req.locale,
|
||||
fallback: req.query['fallback-locale']
|
||||
};
|
||||
modelById(query, {...createAutopopulateOptions(req.query.depth)})
|
||||
modelById(query, { ...createAutopopulateOptions(req.query.depth) })
|
||||
.then(doc => res.json(doc))
|
||||
.catch(err => res.status(httpStatus.INTERNAL_SERVER_ERROR).json({ error: err }));
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const modelById = (query, options)=> {
|
||||
const modelById = (query, options) => {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
query.Model.findOne({ _id: query.id }, {}, options, (err, doc) => {
|
||||
@@ -11,10 +11,12 @@ const modelById = (query, options)=> {
|
||||
|
||||
if (query.locale) {
|
||||
doc.setLocale(query.locale, query.fallback);
|
||||
const json = doc.toJSON({ virtuals: true });
|
||||
result = json;
|
||||
result = doc.toJSON({ virtuals: true });
|
||||
}
|
||||
resolve(result);
|
||||
|
||||
resolve(options.returnRawDoc
|
||||
? doc
|
||||
: result);
|
||||
})
|
||||
})
|
||||
};
|
||||
|
||||
@@ -1,25 +1,32 @@
|
||||
import express from 'express';
|
||||
import passport from 'passport';
|
||||
import uploadsCtrl from '../controllers/uploads.controller';
|
||||
import { upload, update } from '../controllers/media.controller';
|
||||
import { query } from '../requestHandlers';
|
||||
import bindModel from '../middleware/bindModel';
|
||||
import Media from '../models/Media.model';
|
||||
import mediaModelLoader from '../models/Media.model';
|
||||
|
||||
const router = express.Router();
|
||||
const mediaRoutes = config => {
|
||||
|
||||
router.all('*', bindModel(Media));
|
||||
const mediaModel = mediaModelLoader(config); // Needs config for intl
|
||||
router.all('*', bindModel(mediaModel));
|
||||
|
||||
router
|
||||
.route('')
|
||||
.post(
|
||||
passport.authenticate('jwt', { session: false }),
|
||||
(req, res, next) => uploadsCtrl.upload(req, res, next, config)
|
||||
(req, res, next) => upload(req, res, next, config)
|
||||
);
|
||||
|
||||
router
|
||||
.route('/:_id')
|
||||
.put(
|
||||
passport.authenticate('jwt', { session: false }),
|
||||
(req, res, next) => update(req, res, next, config)
|
||||
);
|
||||
|
||||
router.route('')
|
||||
.get(
|
||||
passport.authenticate('jwt', { session: false }),
|
||||
query
|
||||
);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import sharp from 'sharp';
|
||||
import sizeOf from 'image-size';
|
||||
const { promisify } = require('util');
|
||||
const sizeOf = promisify(require('image-size'));
|
||||
|
||||
function getOutputImageName(sourceImage, size) {
|
||||
let extension = sourceImage.split('.').pop();
|
||||
@@ -7,25 +8,27 @@ function getOutputImageName(sourceImage, size) {
|
||||
return `${filenameWithoutExtension}-${size.width}x${size.height}.${extension}`;
|
||||
}
|
||||
|
||||
export function resize(config, file) {
|
||||
export async function resizeAndSave(config, file) {
|
||||
let sourceImage = `${config.staticDir}/${file.name}`;
|
||||
|
||||
sizeOf(sourceImage, (err, dimensions) => {
|
||||
for (let size of config.imageSizes) {
|
||||
if (size.width > dimensions.width) {
|
||||
console.log(`${size.width} is greater than actual width ${dimensions.width}`);
|
||||
let outputSizes = [];
|
||||
try {
|
||||
const dimensions = await sizeOf(sourceImage);
|
||||
for (let desiredSize of config.imageSizes) {
|
||||
if (desiredSize.width > dimensions.width) {
|
||||
continue;
|
||||
}
|
||||
let outputImageName = getOutputImageName(sourceImage, size);
|
||||
sharp(sourceImage)
|
||||
.resize(size.width, size.height, {
|
||||
position: size.crop || 'centre'
|
||||
let outputImageName = getOutputImageName(sourceImage, desiredSize);
|
||||
await sharp(sourceImage)
|
||||
.resize(desiredSize.width, desiredSize.height, {
|
||||
position: desiredSize.crop || 'centre'
|
||||
})
|
||||
.toFile(outputImageName, (err) => {
|
||||
if (err) console.log('Error writing resized file', err);
|
||||
console.log(`Resized image from ${dimensions.width}x${dimensions.height} to ${size.width}x${size.height}`);
|
||||
});
|
||||
|
||||
.toFile(outputImageName);
|
||||
outputSizes.push({ height: desiredSize.height, width: desiredSize.width });
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.log('error in resize and save', e.message);
|
||||
}
|
||||
|
||||
return outputSizes;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user