Context
As a part of the exercise i was wondering - “is it possible to attach all files for particular folder?”. And here is a blog post how it was achieved.
TLDR: Yes it is possible. Scroll to the end of the article to see full example.
Part 1. Input component
Let’s design <input />
component to add support DND(drag and drop) support, since folder uploader works only with DND functionality.
Add Some Styles:
Stylish result will be looks like this 💅:
Result of the component
Part 2. DND handler
As you may see in previous part - we left handleDrop
empty. Now we put some code and see the results:
Part 3. Directory Reader
To convert files - we ‘ll write scanFiles
function. It’s returns Promise
since Reader.readEntries
returns callback. Also, this function will be recursive, since when we read the directory - we should call a reader to get all files/folders inside.
⚠️ From MDN. Note: To read all files in a directory,
readEntries
needs to be called repeatedly until it returns an empty array. In Chromium-based browsers, the following example will only return a max of 100 entries.
⚠️ webkitGetAsEntry API has no official W3C or WHATWG specification. It will works only in chromium-based browsers.
Let me explain this piece of sh*t line by line.
- If item is file - return file (as array)
- if item is directory:
- create a
directoryReader
. - create a
Promise
.- call
readEntries
and for each entry callscanFiles
recursively. - call
directoryReader.readEntries
once again. SincereadEntries
returns only first 100 elements, but folders can contains more than 100 files. - resolve the promise with all collected entries. (I do
flat()
call since File handler also returns array.)
- call
- Return Promise result.
- create a
Performance
Performance can be slow since we doesn’t know about how many items inside directories (if items less than 100 - performance is good enough.) But the problem is - when folder contains thousands of files like in screenshot below
9k items - 9k function calls as a microtask.
Thoughts
- It’s better to use
iterator
instead ofPromise
with full result. It helps with performance issue. - Maybe WASM module will be better but not sure about support of the FS system - need to research.
Have a good day 👋. See you soon!