payloadcms / payload

Payload is the open-source, fullstack Next.js framework, giving you instant backend superpowers. Get a full TypeScript backend and admin panel instantly. Use Payload as a headless CMS or for building powerful applications.
https://payloadcms.com
MIT License
23.12k stars 1.44k forks source link

Slow local storage upload because of safe filename check #7192

Open denolfe opened 1 month ago

denolfe commented 1 month ago

Describe the Bug

Storing a single image in Payload takes ~1-2 seconds at a minimum because of the safe filename check that is performed in order to determine if the filename is already taken. If it is, we append -<number> on the end.

It was reported that explicitly setting the filename to be unique didn't help, either.

One possible solution is to append a unique string on all uploads. This would avoid having to do the uniqueness check. Ideally, this would be behind a flag if implemented.

Payload Version

2.x

Adapters and Plugins

No response

tak-amboss commented 1 month ago

One possible solution is to append a unique string on all uploads. This would avoid having to do the uniqueness check. Ideally, this would be behind a flag if implemented.

Instead of appending a unique string on all uploads, you could also append a unique string instead of the -<number>. This would still require the filename check, but only once, which is certainly acceptable. This way it wouldn't be a breaking change and quite straight forward.

JarrodMFlesch commented 1 month ago

Instead of appending a unique string on all uploads, you could also append a unique string instead of the -. This would still require the filename check, but only once, which is certainly acceptable. This way it wouldn't be a breaking change and quite straight forward.

Could we perform a count query with the right filtering/regex? Even a unique string has the chance that it will not be unique.

r1tsuu commented 1 month ago

For this, I created a beforeOperation hook does append UUID to a filename

  ({ args, operation, req }) => {
        if ((operation === 'update' || operation === 'create') && req.file && req.file.name) {
          const parsed = path.parse(req.file.name);

          const newName = `${parsed.name}-${crypto.randomUUID()}${parsed.ext}`;

          if (args.data) {
            args.data.originalFilename = req.file.name;
            args.data.filename = newName;
          }

          req.file.name = newName;
        }
      }

Maybe it would be nice to have something like generateFilename option for upload, with some implementation by default? This way we can even preserve the current behavior.