feat: image dimensions rework (#5824)

This commit is contained in:
James Mikrut
2024-04-15 10:22:40 -04:00
committed by GitHub
6 changed files with 99 additions and 53 deletions

View File

@@ -52,6 +52,7 @@
"find-up": "4.1.0",
"get-tsconfig": "^4.7.2",
"http-status": "1.6.2",
"image-size": "^1.1.1",
"joi": "^17.12.1",
"json-schema-to-typescript": "11.0.3",
"jsonwebtoken": "9.0.1",
@@ -62,10 +63,10 @@
"pino": "8.15.0",
"pino-pretty": "10.2.0",
"pluralize": "8.0.0",
"probe-image-size": "^7.2.3",
"sanitize-filename": "1.6.3",
"scheduler": "0.23.0",
"scmp": "2.1.0"
"scmp": "2.1.0",
"uuid": "^9.0.1"
},
"peerDependencies": {
"@swc/core": "^1.4.13"

View File

@@ -133,7 +133,7 @@ export const generateFileData = async <T>({
}
if (fileSupportsResize || isImage(file.mimetype)) {
dimensions = getImageSize(file)
dimensions = await getImageSize(file)
fileData.width = dimensions.width
fileData.height = dimensions.height
}

View File

@@ -1,14 +1,32 @@
import fs from 'fs'
import probeImageSize from 'probe-image-size'
import sizeOfImport from 'image-size'
import { promisify } from 'util'
import type { PayloadRequest } from '../types/index.js'
import type { ProbedImageSize } from './types.js'
export function getImageSize(file: PayloadRequest['file']): ProbedImageSize {
import { temporaryFileTask } from './tempFile.js'
const { imageSize } = sizeOfImport
const imageSizePromise = promisify(imageSize)
export async function getImageSize(file: PayloadRequest['file']): Promise<ProbedImageSize> {
if (file.tempFilePath) {
const data = fs.readFileSync(file.tempFilePath)
return probeImageSize.sync(data)
return imageSizePromise(file.tempFilePath)
}
return probeImageSize.sync(file.data)
// Tiff file do not support buffers or streams, so we must write to file first
// then retrieve dimensions. https://github.com/image-size/image-size/issues/103
if (file.mimetype === 'image/tiff') {
const dimensions = await temporaryFileTask(
async (filepath: string) => {
fs.writeFileSync(filepath, file.data)
return imageSizePromise(filepath)
},
{ extension: 'tiff' },
)
return dimensions
}
return imageSize(file.data)
}

View File

@@ -0,0 +1,50 @@
import { promises as fsPromises } from 'fs'
import os from 'node:os'
import path from 'node:path'
import { v4 as uuid } from 'uuid'
async function runTask(temporaryPath: string, callback) {
try {
return await callback(temporaryPath)
} finally {
await fsPromises.rm(temporaryPath, { force: true, maxRetries: 2, recursive: true })
}
}
type Options = {
extension?: string
name?: string
}
export const temporaryFileTask = async (callback, options: Options = {}) => {
const filePath = await temporaryFile(options)
return runTask(filePath, callback)
}
async function temporaryFile(options: Options) {
if (options.name) {
if (options.extension !== undefined && options.extension !== null) {
throw new Error('The `name` and `extension` options are mutually exclusive')
}
return path.join(await temporaryDirectory(), options.name)
}
return (
(await getPath()) +
(options.extension === undefined || options.extension === null
? ''
: '.' + options.extension.replace(/^\./, ''))
)
}
async function temporaryDirectory({ prefix = '' } = {}) {
const directory = await getPath(prefix)
await fsPromises.mkdir(directory)
return directory
}
async function getPath(prefix = ''): Promise<string> {
const temporaryDirectory = await fsPromises.realpath(os.tmpdir())
return path.join(temporaryDirectory, prefix + uuid())
}

65
pnpm-lock.yaml generated
View File

@@ -748,6 +748,9 @@ importers:
http-status:
specifier: 1.6.2
version: 1.6.2
image-size:
specifier: ^1.1.1
version: 1.1.1
joi:
specifier: ^17.12.1
version: 17.12.3
@@ -778,9 +781,6 @@ importers:
pluralize:
specifier: 8.0.0
version: 8.0.0
probe-image-size:
specifier: ^7.2.3
version: 7.2.3
sanitize-filename:
specifier: 1.6.3
version: 1.6.3
@@ -790,6 +790,9 @@ importers:
scmp:
specifier: 2.1.0
version: 2.1.0
uuid:
specifier: ^9.0.1
version: 9.0.1
devDependencies:
'@monaco-editor/react':
specifier: 4.5.1
@@ -8253,17 +8256,6 @@ packages:
dependencies:
ms: 2.0.0
/debug@3.2.7:
resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
dependencies:
ms: 2.1.3
dev: false
/debug@4.3.4(supports-color@5.5.0):
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
engines: {node: '>=6.0'}
@@ -10449,6 +10441,14 @@ packages:
resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==}
engines: {node: '>= 4'}
/image-size@1.1.1:
resolution: {integrity: sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==}
engines: {node: '>=16.x'}
hasBin: true
dependencies:
queue: 6.0.2
dev: false
/immer@9.0.21:
resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==}
@@ -12238,18 +12238,6 @@ packages:
/natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
/needle@2.9.1:
resolution: {integrity: sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==}
engines: {node: '>= 4.4.x'}
hasBin: true
dependencies:
debug: 3.2.7
iconv-lite: 0.4.24
sax: 1.3.0
transitivePeerDependencies:
- supports-color
dev: false
/negotiator@0.6.3:
resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
engines: {node: '>= 0.6'}
@@ -13815,16 +13803,6 @@ packages:
engines: {node: '>=6'}
dev: false
/probe-image-size@7.2.3:
resolution: {integrity: sha512-HubhG4Rb2UH8YtV4ba0Vp5bQ7L78RTONYu/ujmCu5nBI8wGv24s4E9xSKBi0N1MowRpxk76pFCpJtW0KPzOK0w==}
dependencies:
lodash.merge: 4.6.2
needle: 2.9.1
stream-parser: 0.3.1
transitivePeerDependencies:
- supports-color
dev: false
/process-nextick-args@2.0.1:
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
dev: true
@@ -13921,6 +13899,12 @@ packages:
resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==}
dev: true
/queue@6.0.2:
resolution: {integrity: sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==}
dependencies:
inherits: 2.0.4
dev: false
/quick-format-unescaped@4.0.4:
resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==}
@@ -14499,6 +14483,7 @@ packages:
/sax@1.3.0:
resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==}
dev: true
/saxes@6.0.0:
resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
@@ -14958,14 +14943,6 @@ packages:
stubs: 3.0.0
dev: true
/stream-parser@0.3.1:
resolution: {integrity: sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ==}
dependencies:
debug: 2.6.9
transitivePeerDependencies:
- supports-color
dev: false
/stream-shift@1.0.3:
resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==}
dev: true

View File

@@ -161,4 +161,4 @@
".next/types/**/*.ts",
"scripts/**/*.ts"
]
}
}