Closed TerrySlack closed 1 week ago
@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.
@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
@TerrySlack I don't think I fully understand the issue you're describing. Are you providing your own getFilesFromEvent
method and you're not getting similar arguments, when called, across browsers?
Note that I'd expect some differences b/t browsers when dealing with this.
@rolandjitsu Did you follow my steps to reproduce the error? I left a detailed account of what happened. Your messages makes me think you didn't review what I added when filling this issue.
So you're saying there should be a difference cross browser? That we need to worry about cross browser issues? Your sample of how to get files from an event doesn't indicate this at all. In fact, why isn't the event itself just passed to the method we implement? I did some digging last year, when I filed this issue, and it's a small plugin used in react-dropzone. It's been awhile, and I can't recall, but it doesn't consistently return the expected file objects.
FireFox returns File objects. Chrome returns FileHanlder objects. Shouldn't the library authors handle this? Not to mention, it's get files from an event. Why is an array of objects returned, in Chrome, instead of the event. Look at how you handle this in the library and you will find the small library lib you guys use that deals with this. It's the culprit. Apologies for not being more specific on which imported lib. I don't have the time to go and dig it up again.
As it took so long to hear back regarding this issue, I wrote my own dropzone library instead. It's consistent across browsers in returning File Objects. It seems to me that getting uploaded files, from an event should be pretty straight forward, but I may be missing something.
Best of luck with this issue. If you find my steps above to replicate were not clear, please let me know.
@TerrySlack I have reviewed what you filled in. I expected a codesandbox (using the sample provided in the issue template) which would have made reproducing your described issue a lot easier. The combination of text and code samples in the issue made it confusing to understand how you're using the lib.
So you're saying there should be a difference cross browser?
This stems from the fact that when the file system access API is used, then the event passed to the function is a list of FileSystemFileHandle
(see https://developer.mozilla.org/en-US/docs/Web/API/Window/showOpenFilePicker). And some browsers support this API and others don't. By default, using this API has been disabled in the latest versions.
Then, there are 2 different usages which, regardless of the aforementioned file system access API, would result in different data: select via file picker or drag and drop. When drag and drop is used, you'll get a DragEvent, and when using the file picker, you'll get a generic event which has a files
object on it's target (see change_event).
That we need to worry about cross browser issues?
There's a reason why we provide a default impl. for the getFilesFromEvent
. So that we provide some basic functionality for handling all these different events. Then, if the users want to use their own impl. then it's up to them to handle all these different events the way they want.
Your sample of how to get files from an event doesn't indicate this at all. In fact, why isn't the event itself just passed to the method we implement?
We can probably improve the documentation around this. But the events are passed as is to the function without any alteration on our end.
FireFox returns File objects. Chrome returns FileHanlder objects. Shouldn't the library authors handle this? Not to mention, it's get files from an event. Why is an array of objects returned, in Chrome, instead of the event.
This is what file-selector does. It handles different events and returns a FileWithPath
list.
Look at how you handle this in the library and you will find the small library lib you guys use that deals with this. It's the culprit.
I don't think I fully understand this statement.
Apologies for not being more specific on which imported lib. I don't have the time to go and dig it up again.
No worries. I understand.
As it took so long to hear back regarding this issue, I wrote my own dropzone library instead. It's consistent across browsers in returning File Objects.
I'm sorry about taking so long to respond. It's good to hear that you managed to sort it out by building your own library. If you could share what you've done perhaps we could see if we can bring some enhancements to this lib.
Best of luck with this issue. If you find my steps above to replicate were not clear, please let me know.
I just need a codesandbox and a clear explanation of what is the issue. Because, as I understand, if you use this lib without any customisation, it should always give you a list of FileWithPath
, but if you provide your own getFilesFromEvent
, then it's expected behaviour that the data passed to the function is different.
@rolandjitsu All good. Up to you to check things out. I've reported the bug. As you can someone else in this thread also experienced the same issue.
"We can probably improve the documentation around this. But the events are passed as is to the function without any alteration on our end." Not true. As mentioned, before you pass anything, it runs through a small library you guys use.
I'm so busy these days, I'm afraid I don't have the time. If you don't feel that your library should work cross browser, then that's your call.
Feel free to close the bug, as I cannot take the time to comment anymore.
Best of luck
Got it @TerrySlack . I'll go ahead and close this. If, at any point, you want to revisit this, we can reopen or open a new one.
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:
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)
FireFox
Desktop (please complete the following information):
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
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?