Automatically regenerate media sizes #1834
Replies: 8 comments 18 replies
-
How to delete old unused thumbnails? |
Beta Was this translation helpful? Give feedback.
-
I had to move payload init function into the regenerateMediaSizes async function. Because my config file was within the src directory I had to update the command to be
|
Beta Was this translation helpful? Give feedback.
-
@jmikrut : Is this script compatible with the cloud storage plugin? I removed the "filePath" section of the update call and it seems that every image in my collection is being iterated over but the sizes area is just empty objects: sizes: { w400: {}, w768: {}, w1024: {} }, |
Beta Was this translation helpful? Give feedback.
-
@andriasang I've managed to make a version of this script that works with plugin-cloud-storage – building on top of @ChristopherNowlan script and with a huge help from @jmikrut on Discord. The main point to get it working is: get the media Important to note as well: Check if you have the latest config file in your
|
Beta Was this translation helpful? Give feedback.
-
When I use @jmikrut's script*, images get lost in a random way. Often it works as expected, but sometimes the original file is removed during the process. * adapted to work with payload 1.6.27 async payload.init() |
Beta Was this translation helpful? Give feedback.
-
Hi, is there a problem running this under the current Payload (I'm on 1.15.7) ? I'm getting errors about not finding the collection. I've spent a while trying various things but still not working. If it does work, can someone explain where it should be run from etc please. Thanks |
Beta Was this translation helpful? Give feedback.
-
Here's a version based on @arieltonglet 's excellent script - also for plugin-cloud-storage . In this version only one image is processed at a time. For concurrency (with rate limits) and a larger number of files we'd use https://github.com/sindresorhus/p-limit This is a Typescript file, that can be placed anywhere, but must be run via ts-node in the root of the Payload project (at the same level as the .env file) For example... /* eslint-disable @typescript-eslint/ban-ts-comment */
// @ts-nocheck
import payload from 'payload'
// eslint-disable-next-line
require('dotenv').config()
const { PAYLOAD_SECRET, DATABASE_URI } = process.env
const regenerateMediaSizes = async (): Promise<void> => {
await payload.init({
secret: PAYLOAD_SECRET,
mongoURL: DATABASE_URI,
local: true
})
const media = await payload.find({
collection: 'media',
depth: 0,
limit: 100
})
if (media != null && media.totalDocs > 0) {
payload.logger.info(`Found ${media.totalDocs} media files.`)
for (let index = 0; index < media.docs.length; index++) {
const mediaDoc = media.docs[index]
try {
await fetch(mediaDoc.url)
.then(async (response) => await response.blob())
.then(async (blob) => {
const arrayBuffer = await blob.arrayBuffer()
const buffer = Buffer.from(arrayBuffer, 'binary')
const file = {
data: buffer,
mimetype: blob.type,
name: mediaDoc.filename,
size: mediaDoc.filesize
}
await payload.update({
collection: 'media',
id: mediaDoc.id,
data: mediaDoc,
file,
overwriteExistingFiles: true,
contentType: blob.type
})
payload.logger.info(
`Media ${mediaDoc.id} (${mediaDoc.filename}) regenerated successfully`
)
})
} catch (err) {
payload.logger.error(`Media ${mediaDoc.id} (${mediaDoc.filename}) failed to regenerate`)
console.error(err)
}
}
} else {
payload.logger.info('No media files found.')
}
payload.logger.info('Done!')
process.exit(0)
}
void regenerateMediaSizes() |
Beta Was this translation helpful? Give feedback.
-
For Payload 3 we used: import { getPayload } from 'payload'
import * as dotenv from 'dotenv'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import { importConfig } from 'payload/node'
dotenv.config() // Load environment variables from .env
const __dirname: string = path.dirname(fileURLToPath(import.meta.url))
const payloadConfigPath: string = path.join(__dirname, '../payload.config.ts')
const awaitedConfig = await importConfig(payloadConfigPath)
const payload = await getPayload({ config: awaitedConfig })
// eslint-disable-next-line
import 'dotenv/config'
const regenerateMediaSizes = async (): Promise<void> => {
const media = await payload.find({
collection: 'media',
depth: 0,
limit: 500,
})
if (media != null && media.totalDocs > 0) {
payload.logger.info(`Found ${media.totalDocs} media files.`)
for (let index = 0; index < media.docs.length; index++) {
const mediaDoc = media.docs[index]
const req = {
headers: new Map(), // Or use any object literal
} as PayloadRequestWithData
req.headers.set('origin', process.env.PAYLOAD_URL)
try {
await payload.update({
collection: 'media',
id: mediaDoc.id,
data: mediaDoc,
overwriteExistingFiles: true,
req,
})
payload.logger.info(
`Media ${mediaDoc.id} (${mediaDoc.filename}) successfully and new copy created.`,
)
} catch (err) {
payload.logger.error(`Media ${mediaDoc.id} (${mediaDoc.filename}) failed to regenerate`)
console.error(err)
}
}
} else {
payload.logger.info('No media files found.')
}
payload.logger.info('Done!')
process.exit(0)
}
void regenerateMediaSizes() |
Beta Was this translation helpful? Give feedback.
-
This is a commonly asked topic and it just came up in Discord today, so I figured I would share a quick script that the team and I use for our Payload projects when we need something like WP's "Regenerate Thumbnails" plugin. Basically if you update your
imageSizes
and want to automatically re-run the image transformations for each one of your uploads, this can be super handy.If you save this file as
regenerateMediaSizes.js
, then all you need to do to run it isnode ./regenerateMediaSizes.js
and boom.Related: #434
Beta Was this translation helpful? Give feedback.
All reactions