Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Type of Files differ between Chromium (Chrome, MS Edge) and Fire Fox #1332

Open
TerrySlack opened this issue Dec 3, 2023 · 2 comments
Labels

Comments

@TerrySlack
Copy link

TerrySlack commented Dec 3, 2023

Describe the bug
I'm using react-dropzone in a project. When using FireFox, and either getting the files from acceptedFiles or from getFilesFromEvent, the type of files differs between Chromium browers and FireFox.

When I upload files in FireFox, acceptedFiles or the files in getFilesFrom event are an array of Files. In Chrome or MS Edge, they are an array of FileSystemHandle files. Also, in the getFilesFromEvent, in Chrome, an event is not passed, but an array of FilesSystemHandle files, but in Firefox, it's an event and the sample code taken off your site, to get the files from an event works.

To Reproduce

Steps to reproduce the behavior:

  1. Add react-dropzone to a project.
  2. Add debugger to where you can view accepted files and/or in the getFilesFromEvent
  3. Upload file(s) in Firefox. Note the file type in the array of acceptedFiles is File. Note the event is an event in getFilesFromEvent
  4. Upload file(s) in Chrome or MS Edge. Not the file type in the array of AcceptedFiles is FileSystemHandle. Note the event in getFilesFromEvent is an array of FileSystemHandle
    See the screen shots below

Expected behavior
For acceptedFiles, an array of Files is provided. In getFilesFromEvent, the incoming event is an event.

Screenshots
Chrome (Same array type in MS Edge)

Chrome-shows-FileSystemHandle

FireFox
FieFox-shows-File

Desktop (please complete the following information):

  • OS: Windows 11
  • Browser: Chrome 119.0.6045.200, MS Edge 119.0.2151.97, FireFox 120.1

Additional context
I was able to overcome this issue, in the function I provide for getFilesFromEvent by checking if it's an array and then returning. If not, then I run the code provided in the sample from react-dropzone

In the callback I provide for getFilesFromEvent

 if (Array.isArray(event)) {
        //This happens in Chrome and MS Edge
        return Promise.resolve(event);
    }


    //This is run in Firefox, based on an event.
    const fileList: UpLoadedFileList =
        ((event as InputEvent).dataTransfer ? (event as InputEvent)?.dataTransfer?.files : (event as ChangeEvent<HTMLInputElement>)?.target?.files) ?? defaultFilesObject;

Then where I need to process the files I have the following method to ensure I"m working with a File and Not a FileSystemHandle

Convert the files
const convertFileSystemFileHandleToFile = async (file: FileSystemFileHandle | File) =>
((file as FileSystemFileHandle)?.getFile ? await Promise.resolve((file as FileSystemFileHandle).getFile()) : file) as File;

Elsewhere in the code base, where I first encounter acceptedFiles
void Promise.all(acceptedFiles.map((file: File) => convertFileSystemFileHandleToFile(file))).then((convertedFiles: File[]) => {
setFiles(convertedFiles);
});

Could react-dropzone incorporate this behaviour? Could it ensure an event is passed into getFilesFromEvent?
Could it normalize the file types to ensure it's the File type and not FileSystemHandle, that is passed to our code?

@TerrySlack TerrySlack added the bug label Dec 3, 2023
@Myou5uf
Copy link

Myou5uf commented Dec 5, 2023

@TerrySlack Hello. I also came across this problem. I need to restrict image dimension (width, height), I realized that this should be done in the getFilesFromEvent method. But I can't figure out how to deal with it. Can you share an example of your solution for processing files in the getFilesFromEvent method? I will be grateful.

@TerrySlack
Copy link
Author

TerrySlack commented Dec 7, 2023

@Myou5uf
Above, I mention it.
In the callback you have for getFileFromEvent: At the top, add this:

 if (Array.isArray(event)) {
        //This happens in Chrome and MS Edge. Event is an array of FileSystemHandle objects
        return Promise.resolve(event);
 }

...use the sample code from react-dropzone to get the files from an event otherwise

If it's a chromium browser, it will return the array of FileSystemHandle objects.

Then wherever you need to process the uploaded files you can call this to convert each one to a File if it isn't, or else return it as is

export const convertFileSystemFileHandleToFile = async (file: FileSystemFileHandle | File) => ("getFile" in file ? file.getFile() : file);

It's async, because file.getFile() is async and this method is on a FileSystemHandle object.

Use something like this

const processFiles = async (acceptedFiles: File[]) => {
        // Ensure the acceptedFiles are converted to File objects. Chrome/MS Edge send FileSystemFileHandle instead of File Objects
        const convertedFiles = await Promise.all(acceptedFiles.map(convertFileSystemFileHandleToFile));
        
         //Set state to do whatever
         setState(convertedFiles);
 };

Hope that helps

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants