There are currently 3 ways to access a user’s files. Not all browsers support all of the ways, and I will do my best to document some of the limitations and implementations of each.
Choose files from (or drag/drop them onto) a file input
There is a way to bind to the
change event on a file input, and access the files via
input.files. Additionally, I bind to the
drop event, and access the file collection via
Drag/drop files onto any element
There are at least two tricks to this drop event that might not be obvious at first glance.
The first is that we want to prevent the browser from redirecting if a user misses the drop zone. By binding the drop event on the body, and preventing default.
The next trick is that if the
dragstart event happened on the body, this was caused by the user clicking and dragging an item on the page. We don’t care about the results of the drag/drop event in that case. That is why there is a capturing
dragend events bound to the body, and this bit is checked on the events bound to the dropbox. We can avoid setting active CSS classes and processing the drop event if it was started on the body.
Capture the paste event on the document to access clipboard content.
This is one of the coolest ideas, but flakiest implementations across browsers. I love the idea of being able to print screen or copy a file from my file browser and just paste it into the website.
Cool parts about Copy / Paste
You can print screen, or use the snipping tool in Windows and directly paste this into the screen. Try this out on the demo – it’s pretty neat.
Issues with Copy / Paste from File Browsers
- In OSX – I can copy/paste files out of the Finder, but it only gets the first one. And if the file is a non-image, then it actually pastes the thumbnail of the file type association (so a little PDF icon for a PDF, etc). There is also no filename that gets passed in (so I just call it “Clipboard 1”, “Clipboard 2”, etc.
- In Windows – I can’t seem to copy/paste files out of Explorer.
A neat part about using a plugin for handling the direct
FileReader access is that we can transparently replace the technology behind the scenes, but keep your code the same. There is an option to set
FileReaderJS.sync = true, and if your browser supports it – the files will be read inside of a
WebWorker instead of inside the main event loop in your browser.