Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I tell if I have a list of File objects?

I'm working on some drag-drop stuff right now, and as a normalization step I'd like to check if the list of objects I have are actually Files. It appears that what I normally get from event.dataTransfer is a FileList / DataTransferFileList, but the function I'm writing might end up accepting File objects from a non-event source. So, I was thinking about checking if individual items within are instances of File or DataTransferItem.

However, it seems like what I can actually get out of JS is all over the place. MDN tells me that DataTransfer.files contains a FileList; Chrome Devtools shows it as a DataTransferItemList (in the console). An item within the list should be a 'File', according to MDN, but Devtools shows it as a DataTransferItem. Oddly though, DataTransferItem is undefined in the Devtools console, and certainly doesn't work for an instanceof call. File, FileList, and DataTransferItemList are all there, though.

I haven't even started poking into other browsers yet....

So, my question has two parts:

  1. What's with these variations? Does MDN preference Gecko functionality over an interpretation of the W3C spec? Am I seeing Webkit datatypes in the Devtools console, but these datatypes don't necessarily translate to anything accessible (i.e. a JS constructor) in JS that I can use to instanceof?

  2. How can I tell if something is a list of Files, given all these variations? Should I be relying on some duck typing solution instead of instanceof?

like image 991
ericsoco Avatar asked Oct 24 '25 21:10

ericsoco


1 Answers

So I ended up with something like this:

var knownFiles = [];

// If not already a list, make it a list
if (!files.length) {
    files = [files];
}

// Iterate manually to accommodate Array, FileList, DataTransferItemList
for (i = 0; i < files.length; i++) {
    file = files[i];

    if (Blob && file instanceof Blob) {
        // Safari, Firefox, IE land here
        knownFiles.push(file);
    } else if (file.webkitGetAsEntry) {
        // Chrome wraps Files in DataTransferItems
        knownFiles.push(file.webkitGetAsEntry());
    }
}

return knownFiles;

Most of this came from poking around in browsers (Chrome 41, Safari 8, Firefox 36, and IE 11), but I also had some help from here: https://code.flickr.net/2012/12/10/drag-n-drop/.

Apparently, Chrome is the only browser that bothers with the DataTransferItemList interface, and that adds an additional layer around FileLists and Files returned in the dataTransfer property of drag/drop events.

like image 146
ericsoco Avatar answered Oct 27 '25 12:10

ericsoco



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!