react-dropzone: [BUG] `accept` ignores extensions when used with wildcards

Describe the bug

Using a wildcard for image/* and then declaring file extensions doesn’t seem to work as expected in Firefox and Brave/Chrome.

The following code will let users drop any image type and the jpeg/png file extensions are ignored.

Note (and this is almost more important as we don’t need to react to drop events): The same behaviour can be observed when the file picker dialog opens, it will allow picking other image extensions, not just jpeg and png.

useDropzone({
    accept: {
      'image/*': ['.jpeg', '.png']
    }
})

To Reproduce

Steps to reproduce the behavior:

  1. Go to https://react-dropzone.js.org/#section-accepting-specific-file-types
  2. Scroll to the 2nd example in the Browser limitations section (the one that “works”).
  3. Drag a webp, jpg, gif, heic, heif file onto it
  4. See “all files will be accepted” message

Expected behavior Should only accept jpeg and png.

The desired behaviour can be achieved by using multiple MIME types matching their extension:

useDropzone({
    accept: {
      'image/png': ['.png'],
      'image/jpeg': ['.jpeg'],
   }
})

or leaving out the MIME type entirely (which doesn’t seem to work on Windows as it reverts back to “All files (.)), unless FsAccess is disabled”:

useDropzone({
    accept: {
      '': ['.png', '.jpeg'],
   }
})

See: https://codesandbox.io/s/react-dropzone-example-forked-qcic4f?file=/src/App.js

Screenshots other-files

Desktop (please complete the following information):

  • OS: macOS 11.6.8
  • Browser: Brave v1.41.100
  • Version react-dropzone@14.2.2

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Reactions: 10
  • Comments: 16

Most upvoted comments

It would have been very helpful if the library accept a more generic data structure for accept, one I can think of is:

useDropzone({
    accept: [
        ".ext", "mime/type", { "mime/type": [ ".ext1, ".ext2"] }
    ]
})

This way, you can specify a specific extension without the need to specify the whole mimetype, for example when I want only .jpg and .jpeg files, I shouldn’t need to specify image/jpeg because this makes the input to accept every file extension that have the image/jpeg mimetype, for example .jfif files.

The current accept has limitations.

I need a way to tell dropzone to only accept .jpg and .jpeg but none of the other JPG variants

'image/jpeg': ['.jpg', '.jpeg'],
'image/png': ['.png'],
'image/gif': ['.gif'],
'image/webp': ['.webp'],
'application/pdf': [],

I have the code above but I can still select JFIF possibly other JPG variants. How do I fix this ?

Just came here now after a too optimistic upgrade (didn’t read up on the breaking change introduced in v13), and wanted to leave my +1: This format is way too limited and/or verbose, depending on how you see it. Having the wildcard mime type from the key added to the accept attribute is not expected behavior.

@pzi However, values like image/jpeg pass this regex. So the working solution is to change this:

useDropzone({
    accept: {
      'image/*': [ '.jpeg', '.png' ]
    }
})

to this:

useDropzone({
    accept: {
      'image/jpeg': [ '.jpg', '.jpeg' ],
      'image/png': [ '.png' ]
    }
})

This one is even better:

useDropzone({
    accept: {
      'image/jpeg': [ '.jpg', '.jpeg' ],
      'image/png': []
    }
})

The computed accept string will be: image/jpeg, .jpg, .jpeg, image/png 0 warnings.

Thanks for the suggestion, however, your proposed change defeats the purpose of wildcard types? I don’t want to explicitly state all image extensions to get the same as image/*.

If your code works with all image formats, then you can use something like this:

useDropzone({
    accept: {
      'image/*': []
    }
})

The computed accept string will be: image/*

My code only works with png and jpeg formats so to me it’s suitable a solution like:

useDropzone({
    accept: {
      'image/jpeg': [ '.jpg', '.jpeg' ],
      'image/png': []
    }
})

I could have also avoided to specify every single jpeg format extension but I preferred that way just to stay safe.

Here’s the issue with the “application/pdf” mime type. You can rename the image files to pdf extension and it accepts. Basically, it is not checking the Mime Type but simply extension.

having the same issue.

in the following accept, no file type were accepted.

  const fileUploaderState = useFileUploader({
    onDrop: (acceptedFiles) => {
      setFiles(acceptedFiles);
    },
    accept: {
      'application/vnd.ms-excel': ['.xls', '.slk', '.xla', '.xlt', '.xlw'],
      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': [
        '.xlsx',
      ],
      'text/csv': ['.csv'],
      'text/html': ['.htm', '.html'],
      'text/plain': ['.txt', '.dif'],
      'application/x-iwork-numbers-sffnumbers': ['.numbers'],
      'text/xml': ['.xml'],
      'application/vnd.oasis.opendocument.spreadsheet': ['.ods'],
      'application/vnd.oasis.opendocument.text': ['.odt'],
      'application/octet-stream': [],
      'video/x-dv': [],
      'multipart/related': ['.mhtl'],
      'application/vnd.ms-excel.sheet.binary.macroenabled.12': ['.xlsb'],
      'application/vnd.ms-excel.sheet.macroenabled.12': ['.xlsm'],
      'application/vnd.ms-excel.template.macroenabled.12': ['.xltm'],
      'application/vnd.ms-excel.addin.macroenabled.12': ['.xlam'],
      'application/x-dbase': ['.dbf'],
      'message/rfc822': ['.mht'],
    },
  });

setting '*/text': ['.csv', '.xlsx'], enable both types, although .xlsx mime type is application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.

@pzi However, values like image/jpeg pass this regex.

So the working solution is to change this:

useDropzone({
    accept: {
      'image/*': [ '.jpeg', '.png' ]
    }
})

to this:

useDropzone({
    accept: {
      'image/jpeg': [ '.jpg', '.jpeg' ],
      'image/png': [ '.png' ]
    }
})

This one is even better:

useDropzone({
    accept: {
      'image/jpeg': [ '.jpg', '.jpeg' ],
      'image/png': []
    }
})

The computed accept string will be: image/jpeg, .jpg, .jpeg, image/png

0 warnings.

Thanks for the suggestion, however, your proposed change defeats the purpose of wildcard types? I don’t want to explicitly state all image extensions to get the same as image/*.