Files
payload/src/uploads/imageResizer.ts

87 lines
2.4 KiB
TypeScript

import fs from 'fs';
import sharp from 'sharp';
import sanitize from 'sanitize-filename';
import getImageSize from './getImageSize';
import fileExists from './fileExists';
import { SanitizedCollectionConfig } from '../collections/config/types';
import { FileSizes, ImageSize } from './types';
function getOutputImage(sourceImage: string, size: ImageSize) {
const extension = sourceImage.split('.').pop();
const name = sanitize(sourceImage.substr(0, sourceImage.lastIndexOf('.')) || sourceImage);
return {
name,
extension,
width: size.width,
height: size.height,
};
}
/**
* @description
* @param staticPath Path to save images
* @param config Payload config
* @param savedFilename
* @param mimeType
* @returns image sizes keyed to strings
*/
export default async function resizeAndSave(
staticPath: string,
config: SanitizedCollectionConfig,
savedFilename: string,
mimeType: string,
): Promise<FileSizes> {
const { imageSizes } = config.upload;
const sourceImage = `${staticPath}/${savedFilename}`;
const dimensions = await getImageSize(sourceImage);
const sizes = imageSizes
.filter((desiredSize) => desiredSize.width < dimensions.width)
.map(async (desiredSize) => {
const resized = await sharp(sourceImage)
.resize(desiredSize.width, desiredSize.height, {
position: desiredSize.crop || 'centre',
});
const bufferObject = await resized.toBuffer({
resolveWithObject: true,
});
const outputImage = getOutputImage(savedFilename, desiredSize);
const imageNameWithDimensions = `${outputImage.name}-${bufferObject.info.width}x${bufferObject.info.height}.${outputImage.extension}`;
const imagePath = `${staticPath}/${imageNameWithDimensions}`;
const fileAlreadyExists = await fileExists(imagePath);
if (fileAlreadyExists) {
fs.unlinkSync(imagePath);
}
await resized.toFile(imagePath);
return {
name: desiredSize.name,
width: bufferObject.info.width,
height: bufferObject.info.height,
filename: imageNameWithDimensions,
filesize: bufferObject.info.size,
mimeType,
};
});
const savedSizes = await Promise.all(sizes);
return savedSizes.reduce((results, size) => ({
...results,
[size.name]: {
width: size.width,
height: size.height,
filename: size.filename,
mimeType: size.mimeType,
filesize: size.filesize,
},
}), {});
}