refs #5576 feat: add symbolLink in folder when original is bigger than folder
This commit is contained in:
parent
a5237281d6
commit
3a1520cfea
|
@ -2,132 +2,222 @@ const fs = require('fs-extra');
|
|||
const path = require('path');
|
||||
const gm = require('gm');
|
||||
const crypto = require('crypto');
|
||||
|
||||
const {models} = require('vn-loopback/server/server');
|
||||
const PNG = 'png';
|
||||
const FORMAT = PNG;
|
||||
const DEFAULT_GRAVITY = 'Center';
|
||||
const DEFAULT_QUALITY = 100;
|
||||
const SIZE_UNIT = 'x';
|
||||
const formatWidthHeight = (width, height) => `${width}${SIZE_UNIT}${height}`;
|
||||
const parseSize = value => formatWidthHeight(value.width, value.height).split(SIZE_UNIT);
|
||||
module.exports = Self => {
|
||||
require('../methods/image/download')(Self);
|
||||
require('../methods/image/upload')(Self);
|
||||
require('../methods/image/scrub')(Self);
|
||||
|
||||
Self.resize = async function({collectionName, srcFile, fileName, entityId}) {
|
||||
const models = Self.app.models;
|
||||
|
||||
const collection = await models.ImageCollection.findOne(
|
||||
{
|
||||
fields: [
|
||||
'id',
|
||||
'maxWidth',
|
||||
'maxHeight',
|
||||
'model',
|
||||
'property',
|
||||
],
|
||||
where: {name: collectionName},
|
||||
include: {
|
||||
relation: 'sizes',
|
||||
scope: {
|
||||
fields: ['width', 'height', 'crop'],
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
Self.handleFolderDestination = async fileName => {
|
||||
// Insert image row
|
||||
const imageName = path.parse(fileName).name;
|
||||
const shasum = crypto.createHash('sha1');
|
||||
shasum.update(imageName);
|
||||
const hash = shasum.digest('hex');
|
||||
const {name} = path.parse(fileName);
|
||||
const hash = crypto.createHash('sha1').update(name).digest('hex');
|
||||
const pairs = hash.match(/(..?)/g);
|
||||
const imageConfig = await models.ImageConfig.findOne({fields: ['dirLevels']});
|
||||
const firstPairs = pairs.slice(0, imageConfig.dirLevels).reverse();
|
||||
const dstDir = firstPairs.join('/');
|
||||
const {dirLevels} = await models.ImageConfig.findOne({
|
||||
fields: ['dirLevels'],
|
||||
});
|
||||
const dstDir = pairs.slice(0, dirLevels).reverse().join('/');
|
||||
|
||||
await models.Image.upsertWithWhere(
|
||||
{
|
||||
name: imageName,
|
||||
collectionFk: collectionName
|
||||
return {name, dstDir};
|
||||
};
|
||||
Self.getCollection = async collectionName => {
|
||||
const collection = await models.ImageCollection.findOne({
|
||||
fields: ['id', 'maxWidth', 'maxHeight', 'model', 'property'],
|
||||
where: {name: collectionName},
|
||||
include: {
|
||||
relation: 'sizes',
|
||||
scope: {
|
||||
fields: ['width', 'height', 'crop'],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return collection;
|
||||
};
|
||||
|
||||
Self.getCollectionDir = async collectionName => {
|
||||
const container = await models.ImageContainer.container(collectionName);
|
||||
const rootPath = container.client.root;
|
||||
const collectionDir = path.join(rootPath, collectionName);
|
||||
return collectionDir;
|
||||
};
|
||||
|
||||
Self.getFullSizePath = (fileName, collectionDir, dstDir) => {
|
||||
const fullSizePath = path.join(collectionDir, `full/${dstDir}`);
|
||||
const fullSizeOriginalPath = path.join(collectionDir, `full`);
|
||||
const toFullSizePath = `${fullSizePath}/${fileName}`;
|
||||
const toFullSizeOriginalPath = `${fullSizeOriginalPath}/${fileName}`;
|
||||
return {
|
||||
fullSizePath,
|
||||
toFullSizePath,
|
||||
toFullSizeOriginalPath
|
||||
};
|
||||
};
|
||||
Self.removeLink = async(child, parent = null) => {
|
||||
try {
|
||||
await fs.unlink(child);
|
||||
} catch (e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
try {
|
||||
await fs.symlink(parent, child);
|
||||
} catch (e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
};
|
||||
Self.createLink = async(parent, child = null) => {
|
||||
try {
|
||||
const exists = await fs.exists(parent);
|
||||
if (exists)
|
||||
await fs.unlink(parent);
|
||||
} catch (e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
try {
|
||||
await fs.symlink(child, parent);
|
||||
const link = await fs.readlink(parent);
|
||||
console.log(link);
|
||||
} catch (e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
};
|
||||
|
||||
Self.resize = async function({
|
||||
collectionName,
|
||||
srcFile,
|
||||
fileName,
|
||||
entityId,
|
||||
}) {
|
||||
const {name, dstDir} = await Self.handleFolderDestination(fileName);
|
||||
try {
|
||||
await models.Image.upsertWithWhere({
|
||||
name,
|
||||
collectionFk: collectionName,
|
||||
},
|
||||
{
|
||||
name: imageName,
|
||||
name,
|
||||
collectionFk: collectionName,
|
||||
updated: Date.vnNow() / 1000,
|
||||
}
|
||||
);
|
||||
});
|
||||
} catch (e) {
|
||||
debugger;
|
||||
throw new Error(e);
|
||||
}
|
||||
const collection = await Self.getCollection(collectionName);
|
||||
const {maxWidth, maxHeight} = collection;
|
||||
|
||||
// Update entity image file name
|
||||
const model = models[collection.model];
|
||||
if (!model) throw new Error('No matching model found');
|
||||
|
||||
const entity = await model.findById(entityId);
|
||||
if (entity) {
|
||||
await entity.updateAttribute(
|
||||
collection.property,
|
||||
imageName
|
||||
);
|
||||
}
|
||||
if (entity)
|
||||
await entity.updateAttribute(collection.property, name);
|
||||
|
||||
// Resize
|
||||
const container = await models.ImageContainer.container(
|
||||
collectionName
|
||||
);
|
||||
const rootPath = container.client.root;
|
||||
const collectionDir = path.join(rootPath, collectionName);
|
||||
const collectionDir = await Self.getCollectionDir(collectionName);
|
||||
|
||||
// To max size
|
||||
const {maxWidth, maxHeight} = collection;
|
||||
const fullSizePath = path.join(collectionDir, `full/${dstDir}`);
|
||||
const fullSizeOriginalPath = path.join(collectionDir, `full`);
|
||||
const toFullSizePath = `${fullSizePath}/${fileName}`;
|
||||
const toFullSizeOriginalPath = `${fullSizeOriginalPath}/${fileName}`;
|
||||
const _fullSizePath = Self.getFullSizePath(fileName, collectionDir, dstDir);
|
||||
|
||||
await fs.mkdir(fullSizePath, {recursive: true});
|
||||
await new Promise((resolve, reject) => {
|
||||
gm(srcFile)
|
||||
.resize(maxWidth, maxHeight, '>')
|
||||
.setFormat('png')
|
||||
.quality(100)
|
||||
.write(toFullSizePath, function(err) {
|
||||
if (err) reject(err);
|
||||
if (!err) resolve();
|
||||
});
|
||||
const {fullSizePath, toFullSizePath, toFullSizeOriginalPath} = _fullSizePath;
|
||||
try {
|
||||
await fs.mkdir(fullSizePath, {recursive: true});
|
||||
} catch (e) {
|
||||
debugger;
|
||||
throw new Error(e);
|
||||
}
|
||||
const gmInstance = gm(srcFile);
|
||||
let fileWidth = null;
|
||||
let fileHeight = null;
|
||||
|
||||
gmInstance.size(function(err, size) {
|
||||
if (err) console.error(err);
|
||||
[fileWidth, fileHeight] = parseSize(size);
|
||||
});
|
||||
try {
|
||||
await fs.unlink(toFullSizeOriginalPath);
|
||||
} catch (e) {}
|
||||
await fs.symlink(toFullSizeOriginalPath, toFullSizePath, 'file');
|
||||
|
||||
// To collection sizes
|
||||
for (const size of collection.sizes()) {
|
||||
const {width, height} = size;
|
||||
|
||||
const sizePath = path.join(collectionDir, `${width}x${height}/${dstDir}`);
|
||||
const toSizePath = `${sizePath}/${fileName}`;
|
||||
const sizeOriginalPath = path.join(collectionDir, `${width}x${height}`);
|
||||
const toSizeOriginalPath = `${sizeOriginalPath}/${fileName}`;
|
||||
|
||||
await fs.mkdir(sizePath, {recursive: true});
|
||||
await new Promise((resolve, reject) => {
|
||||
const gmInstance = gm(srcFile);
|
||||
|
||||
if (size.crop) {
|
||||
gmInstance
|
||||
.resize(width, height, '^')
|
||||
.gravity('Center')
|
||||
.crop(width, height);
|
||||
}
|
||||
|
||||
if (!size.crop) gmInstance.resize(width, height, '>');
|
||||
|
||||
gmInstance
|
||||
.setFormat('png')
|
||||
.quality(100)
|
||||
.write(toSizePath, function(err) {
|
||||
.resize(maxWidth, maxHeight, '>')
|
||||
.setFormat(PNG)
|
||||
.quality(DEFAULT_QUALITY)
|
||||
.write(toFullSizePath + `.${FORMAT}`, function(err, data) {
|
||||
if (err) reject(err);
|
||||
if (!err) resolve();
|
||||
if (!err) resolve(data);
|
||||
});
|
||||
});
|
||||
} catch (e) {
|
||||
debugger;
|
||||
throw new Error(e);
|
||||
}
|
||||
|
||||
await Self.createLink(toFullSizeOriginalPath, toFullSizePath);
|
||||
/* try {
|
||||
await fs.unlink(toFullSizeOriginalPath);
|
||||
} catch (e) {
|
||||
debugger;
|
||||
throw new Error(e);
|
||||
}
|
||||
try {
|
||||
await fs.symlink(toFullSizeOriginalPath, toFullSizePath, 'file');
|
||||
} catch (e) {
|
||||
debugger;
|
||||
throw new Error(e);
|
||||
}*/
|
||||
// To collection sizes
|
||||
for (const size of collection.sizes()) {
|
||||
const [width, height] = parseSize(size);
|
||||
|
||||
const sizePath = path.join(
|
||||
collectionDir,
|
||||
`${formatWidthHeight(width, height)}/${dstDir}`
|
||||
);
|
||||
|
||||
try {
|
||||
await fs.unlink(toSizeOriginalPath);
|
||||
} catch (e) {}
|
||||
await fs.symlink(toSizePath, toSizeOriginalPath);
|
||||
await fs.mkdir(sizePath, {recursive: true});
|
||||
} catch (e) {
|
||||
debugger;
|
||||
throw new Error(e);
|
||||
}
|
||||
|
||||
const toSizePath = `${sizePath}/${fileName}`;
|
||||
if (+fileWidth < +width && +fileHeight < +height) {
|
||||
await new Promise((resolve, reject) => {
|
||||
if (size.crop) {
|
||||
gmInstance
|
||||
.resize(width, height, '^')
|
||||
.gravity(DEFAULT_GRAVITY)
|
||||
.crop(width, height).res(function(err, data) {
|
||||
if (err) reject(err);
|
||||
if (!err) resolve(data);
|
||||
});
|
||||
} else gmInstance.resize(width, height, '>');
|
||||
|
||||
gmInstance
|
||||
.setFormat(PNG)
|
||||
.quality(DEFAULT_QUALITY)
|
||||
.write(toSizePath + `.${FORMAT}`, function(err, data) {
|
||||
if (err) reject(err);
|
||||
if (!err) resolve(data);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const sizeOriginalPath = path.join(
|
||||
collectionDir,
|
||||
formatWidthHeight(width, height)
|
||||
);
|
||||
|
||||
const toSizeOriginalPath = `${sizeOriginalPath}/${fileName}`;
|
||||
|
||||
// if (fileWidth > width && fileHeight < height)
|
||||
await Self.createLink(toSizeOriginalPath, toSizePath);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue