question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Potential collision when two uploaded file name share the same name

See original GitHub issue

Hi!

Thank you for the awesome library - we are currently using this for a project.

One problem we have faced currently is that when the file names for two uploaded files collide, possibly for different entities, the file gets replaced by the newer upload.

For example, consider a schema with the following images field.

    images: {
      title: "Images",
      dataType: "array",
      of: {
        dataType: "string",
        config: {
          storageMeta: {
            mediaType: "image",
            storagePath: "images",
            acceptedFiles: ["image/*"],
          },
        },
      },
    },

To reproduce:

  1. Create an entity with an uploaded file of image.jpg.
  2. Create another entity with a different uploaded file, but also named image.jpg.
  3. Refresh the page

Expected result: The newly created entity should have a different linked image than the previous entity.

Current behavior: (Tested in 0.30.1) The newer upload will replace the older upload file since the name is colliding.


To our understanding, there are currently no configurables regarding the file names. I think we can do some of the following: (Excuse the lame naming here- naming things are so hard!)

  1. Allow a hashed filename/UUID filename/user-provided function to generate the filenames.
          storageMeta: {
            mediaType: "image",
            storagePath: "images",
            acceptedFiles: ["image/*"],

            // a. Once set, the filename would be hashed by its content-hash like SHA256, e.g. `ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad.jpg`
            fileNameHash: "sha256",

            // b. Once set, the filename would be auto-generated by UUID v4, e.g. `36c8e6b9-4862-4901-b7f9-2a6f4b3503a7.jpg`
            fileNameUuid: true,

            // c. Once set, the filename can be provided by a user-provided function, who may then calculate it various means:
            fileName: function ({ entityId, sequence, extension }) {
              return `${entityId}-${sequence}.${extension}`;
            },
          },
  1. Allow the storagePath to be a user-provided function so that it can be prefixed/suffixed according to the entityId. That way even when the image names in different entities collide, they won’t affect each other.
          storageMeta: {
            mediaType: "image",
            storagePath: function (entityId) {
              return `images/${entityId}`,
            },
            acceptedFiles: ["image/*"],
          },
  1. Automatically rename the newly uploaded file with something else (e.g. image-2.jpg when we already have image.jpg).

I personally prefer a combination of 1c and 2 to solve this particular use case. What do you think? Thank you!

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:10 (8 by maintainers)

github_iconTop GitHub Comments

1reaction
ciriousjokercommented, Sep 15, 2022

Here’s my solution to append an md5 hash to the uploaded filename:

/** Appends a hash to the end of the filename to avoid name collisions. */
export async function hashFilename(context: UploadedFileContext): Promise<string> {
  const parts = context.file.name.split(".");
  const basename = parts.slice(0, parts.length - 1);
  const ext = parts[parts.length - 1];
  return `${basename}~${await getHash(context.file)}.${ext}`;
}

// Implement file upload using hashes (via js-md5):
// https://github.com/Camberi/firecms/issues/64
async function getHash(file: File): Promise<string> {
  return new Promise((resolve, reject) => {
    console.log("Generate Hash...");
    const reader = new FileReader();
    reader.onload = (event) => {
      const content = event.target?.result;
      if (content === null || content === undefined) {
        reject("Couldn't calculate hash.");
        return;
      }
      resolve(md5(content));
    };
    reader.readAsArrayBuffer(file);
  });
}
  • This only works since v2.0.0-alpha.30 because of #376
1reaction
fgatti675commented, Mar 22, 2021

Hi @netsgnut First of all thanks a lot for the catch and your suggestions! About the solutions you propose, I would definitely go with the solutions 1c and 2. Having callbacks in those fields is easy to implement and gives the developers all the flexibility they need. The hash and the UUID solutions seem fine but we would need to bring in at least one additional library to the CMS, and developers can still do it manually if they need to with the callback methods. I’ll work on it this week when I find some free time 😃

Read more comments on GitHub >

github_iconTop Results From Across the Web

It is possible that Date.now() for file names to create collisions?
I am wondering if there is a possibility (and how to achieve it) to get two images with the same name, because the...
Read more >
Fixing invalid characters and colliding file names
This error happens when you try to create, rename or save a file to a folder that already contains a file with the...
Read more >
File name collision when including single stranded and ...
When running single stranded and double stranded libraries of the same sample, it complains about duplicated names after the merging step. Steps ...
Read more >
CWE-646: Reliance on File Name or Extension of Externally ...
The software allows a file to be uploaded, but it relies on the file name or extension of the file to determine the...
Read more >
Name Collision Resources & Information - ICANN
A name collision occurs when an attempt to resolve a name used in a private name space (e.g. under a non-delegated Top-Level Domain,...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found