Merge pull request #1757 from payloadcms/fix/#1738-svg-image-sizes
fix: #1738 save image dimensions to svg uploads
This commit is contained in:
@@ -12,6 +12,7 @@ import getSafeFileName from './getSafeFilename';
|
|||||||
import resizeAndSave from './imageResizer';
|
import resizeAndSave from './imageResizer';
|
||||||
import { FileData, FileToSave } from './types';
|
import { FileData, FileToSave } from './types';
|
||||||
import canResizeImage from './canResizeImage';
|
import canResizeImage from './canResizeImage';
|
||||||
|
import isImage from './isImage';
|
||||||
|
|
||||||
type Args = {
|
type Args = {
|
||||||
config: SanitizedConfig,
|
config: SanitizedConfig,
|
||||||
@@ -67,7 +68,12 @@ export const generateFileData = async ({
|
|||||||
const shouldResize = canResizeImage(file.mimetype);
|
const shouldResize = canResizeImage(file.mimetype);
|
||||||
let fsSafeName: string;
|
let fsSafeName: string;
|
||||||
let resized: Sharp | undefined;
|
let resized: Sharp | undefined;
|
||||||
let dimensions: ProbedImageSize;
|
let dimensions;
|
||||||
|
let fileBuffer;
|
||||||
|
let bufferInfo;
|
||||||
|
let ext;
|
||||||
|
let mime;
|
||||||
|
|
||||||
if (shouldResize) {
|
if (shouldResize) {
|
||||||
if (resizeOptions) {
|
if (resizeOptions) {
|
||||||
resized = sharp(file.data)
|
resized = sharp(file.data)
|
||||||
@@ -76,34 +82,46 @@ export const generateFileData = async ({
|
|||||||
if (formatOptions) {
|
if (formatOptions) {
|
||||||
resized = (resized ?? sharp(file.data)).toFormat(formatOptions.format, formatOptions.options);
|
resized = (resized ?? sharp(file.data)).toFormat(formatOptions.format, formatOptions.options);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isImage(file.mimetype)) {
|
||||||
dimensions = await getImageSize(file);
|
dimensions = await getImageSize(file);
|
||||||
fileData.width = dimensions.width;
|
fileData.width = dimensions.width;
|
||||||
fileData.height = dimensions.height;
|
fileData.height = dimensions.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileBuffer = resized ? (await resized.toBuffer()) : file.data;
|
if (resized) {
|
||||||
const bufferInfo = await fromBuffer(fileBuffer);
|
fileBuffer = await resized.toBuffer({ resolveWithObject: true });
|
||||||
let mime = bufferInfo?.mime ?? file.mimetype;
|
bufferInfo = await fromBuffer(fileBuffer.data);
|
||||||
const ext = resized ? bufferInfo.ext : file.name.split('.').pop();
|
|
||||||
const fileSize = fileBuffer.length;
|
mime = bufferInfo.mime;
|
||||||
|
ext = bufferInfo.ext;
|
||||||
|
fileData.width = fileBuffer.info.width;
|
||||||
|
fileData.height = fileBuffer.info.height;
|
||||||
|
fileData.filesize = fileBuffer.data.length;
|
||||||
|
} else {
|
||||||
|
mime = file.mimetype;
|
||||||
|
fileData.filesize = file.size;
|
||||||
|
ext = file.name.split('.').pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mime === 'application/xml' && ext === 'svg') mime = 'image/svg+xml';
|
||||||
|
fileData.mimeType = mime;
|
||||||
|
|
||||||
const baseFilename = sanitize(file.name.substring(0, file.name.lastIndexOf('.')) || file.name);
|
const baseFilename = sanitize(file.name.substring(0, file.name.lastIndexOf('.')) || file.name);
|
||||||
fsSafeName = `${baseFilename}.${ext}`;
|
fsSafeName = `${baseFilename}.${ext}`;
|
||||||
|
|
||||||
if (mime === 'application/xml' && ext === 'svg') mime = 'image/svg+xml';
|
|
||||||
|
|
||||||
if (!overwriteExistingFiles) {
|
if (!overwriteExistingFiles) {
|
||||||
fsSafeName = await getSafeFileName(Model, staticPath, fsSafeName);
|
fsSafeName = await getSafeFileName(Model, staticPath, `${baseFilename}.${ext}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileData.filename = fsSafeName;
|
||||||
|
|
||||||
filesToSave.push({
|
filesToSave.push({
|
||||||
path: `${staticPath}/${fsSafeName}`,
|
path: `${staticPath}/${fsSafeName}`,
|
||||||
buffer: fileBuffer,
|
buffer: fileBuffer?.data || file.data,
|
||||||
});
|
});
|
||||||
|
|
||||||
fileData.filename = fsSafeName || (!overwriteExistingFiles ? await getSafeFileName(Model, staticPath, file.name) : file.name);
|
|
||||||
fileData.filesize = fileSize || file.size;
|
|
||||||
fileData.mimeType = mime || (await fromBuffer(file.data)).mime;
|
|
||||||
|
|
||||||
if (Array.isArray(imageSizes) && shouldResize) {
|
if (Array.isArray(imageSizes) && shouldResize) {
|
||||||
req.payloadUploadSizes = {};
|
req.payloadUploadSizes = {};
|
||||||
const { sizeData, sizesToSave } = await resizeAndSave({
|
const { sizeData, sizesToSave } = await resizeAndSave({
|
||||||
|
|||||||
@@ -5,13 +5,14 @@ import sharp from 'sharp';
|
|||||||
import { SanitizedCollectionConfig } from '../collections/config/types';
|
import { SanitizedCollectionConfig } from '../collections/config/types';
|
||||||
import { PayloadRequest } from '../express/types';
|
import { PayloadRequest } from '../express/types';
|
||||||
import fileExists from './fileExists';
|
import fileExists from './fileExists';
|
||||||
import { ProbedImageSize } from './getImageSize';
|
|
||||||
import { FileSizes, FileToSave, ImageSize } from './types';
|
import { FileSizes, FileToSave, ImageSize } from './types';
|
||||||
|
|
||||||
|
type Dimensions = { width?: number, height?: number }
|
||||||
|
|
||||||
type Args = {
|
type Args = {
|
||||||
req: PayloadRequest
|
req: PayloadRequest
|
||||||
file: Buffer
|
file: Buffer
|
||||||
dimensions: ProbedImageSize
|
dimensions: Dimensions
|
||||||
staticPath: string
|
staticPath: string
|
||||||
config: SanitizedCollectionConfig
|
config: SanitizedCollectionConfig
|
||||||
savedFilename: string
|
savedFilename: string
|
||||||
@@ -118,7 +119,7 @@ function createImageName(
|
|||||||
return `${outputImage.name}-${bufferObject.info.width}x${bufferObject.info.height}.${extension}`;
|
return `${outputImage.name}-${bufferObject.info.width}x${bufferObject.info.height}.${extension}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function needsResize(desiredSize: ImageSize, dimensions: ProbedImageSize): boolean {
|
function needsResize(desiredSize: ImageSize, dimensions: Dimensions): boolean {
|
||||||
return (typeof desiredSize.width === 'number' && desiredSize.width <= dimensions.width)
|
return (typeof desiredSize.width === 'number' && desiredSize.width <= dimensions.width)
|
||||||
|| (typeof desiredSize.height === 'number' && desiredSize.height <= dimensions.height);
|
|| (typeof desiredSize.height === 'number' && desiredSize.height <= dimensions.height);
|
||||||
}
|
}
|
||||||
|
|||||||
15
test/uploads/image.svg
Normal file
15
test/uploads/image.svg
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<svg width="260" height="260" viewBox="0 0 260 260" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<style>
|
||||||
|
path {
|
||||||
|
fill: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
path {
|
||||||
|
fill: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<path d="M120.59 8.5824L231.788 75.6142V202.829L148.039 251.418V124.203L36.7866 57.2249L120.59 8.5824Z" />
|
||||||
|
<path d="M112.123 244.353V145.073L28.2114 193.769L112.123 244.353Z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 437 B |
@@ -26,7 +26,7 @@ describe('Collections - Uploads', () => {
|
|||||||
|
|
||||||
describe('REST', () => {
|
describe('REST', () => {
|
||||||
describe('create', () => {
|
describe('create', () => {
|
||||||
it('creates from form data', async () => {
|
it('creates from form data given a png', async () => {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('file', fs.createReadStream(path.join(__dirname, './image.png')));
|
formData.append('file', fs.createReadStream(path.join(__dirname, './image.png')));
|
||||||
|
|
||||||
@@ -56,6 +56,29 @@ describe('Collections - Uploads', () => {
|
|||||||
expect(doc.sizes).toHaveProperty('mobile');
|
expect(doc.sizes).toHaveProperty('mobile');
|
||||||
expect(doc.sizes).toHaveProperty('icon');
|
expect(doc.sizes).toHaveProperty('icon');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('creates from form data given an svg', async () => {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', fs.createReadStream(path.join(__dirname, './image.svg')));
|
||||||
|
|
||||||
|
const { status, doc } = await client.create({
|
||||||
|
file: true,
|
||||||
|
data: formData,
|
||||||
|
auth: true,
|
||||||
|
headers: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(status).toBe(201);
|
||||||
|
|
||||||
|
// Check for files
|
||||||
|
expect(await fileExists(path.join(__dirname, './media', doc.filename))).toBe(true);
|
||||||
|
|
||||||
|
// Check api response
|
||||||
|
expect(doc.mimeType).toEqual('image/svg+xml');
|
||||||
|
expect(doc.sizes.maintainedAspectRatio.url).toBeUndefined();
|
||||||
|
expect(doc.width).toBeDefined();
|
||||||
|
expect(doc.height).toBeDefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('creates images that do not require all sizes', async () => {
|
it('creates images that do not require all sizes', async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user