code: function entriesApi(items, opts, cb) {
      var fd = new FormData(), files = [], rootPromises = [];
  
      function readEntries(entry, reader, oldEntries, cb) {
        var dirReader = reader || entry.createReader();
        dirReader.readEntries(function(entries) {
          var newEntries = oldEntries ? oldEntries.concat(entries) : entries;
          if (entries.length) {
            setTimeout(readEntries.bind(null, entry, dirReader, newEntries, cb), 0);
          } else {
            cb(newEntries);
          }
        });
      }
  
      function readDirectory(entry, path, resolve) {
        if (!path) path = entry.name;
        readEntries(entry, 0, 0, function(entries) {
          var promises = [];
          entries.forEach(function(entry) {
            promises.push(new Promise(function(resolve) {
              if (entry.isFile) {
                entry.file(function(file) {
                  var p = path + "/" + file.name;
                  fd.append(opts.name, file, p);
                  files.push(p);
                  resolve();
                }, resolve.bind());
              } else readDirectory(entry, path + "/" + entry.name, resolve);
            }));
          });
          Promise.all(promises).then(resolve.bind());
        });
      }
  
      [].slice.call(items).forEach(function(entry) {
        entry = entry.webkitGetAsEntry();
        if (entry) {
          rootPromises.push(new Promise(function(resolve) {
            if (entry.isFile) {
              entry.file(function(file) {
                fd.append(opts.name, file, file.name);
                files.push(file.name);
                resolve();
              }, resolve.bind());
            } else if (entry.isDirectory) {
              readDirectory(entry, null, resolve);
            }
          }));
        }
      });
      Promise.all(rootPromises).then(cb.bind(null, fd, files));
    }
docs: old drag and drop API implemented in Chrome 11+