Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I'm trying to upload whole folders through the browser. I've done a fair bit of tinkering today and discovered that there are a number of great solutions for uploading folders. However, when testing them, they seem to be making the list of files in the folders ready for upload, sans directory structure.

Is there any recommended tool I can use to drag and drop, or even just select and upload, entire folders from my site (and of course, maintain structure)?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
253 views
Welcome To Ask or Share your Answers For Others

1 Answer

Not really officially yet, but there will probably be, available for us mere web-developers* through the Files and Directory API which specs are still in the process of being written, even though chrome and Firefox already implement something similar through a webkit-API*, which allows us to access and navigate dropped directories.

So if we try to use this webkit-API, we could write something like this:

/* constructs a simple directory view from a filesystem */
async function makedir(entries) {

  const systems = entries.map(entry => traverse(entry, {}));
  return Promise.all(systems);

  async function traverse(entry, fs) {
    if (entry.isDirectory) {
      fs[entry.name] = {};
      let dirReader = entry.createReader();
      await new Promise((res, rej) => {
        dirReader.readEntries(async entries => {
          for (let e of entries) {
            await traverse(e, fs[entry.name]);
          }
          res();
        }, rej);
      });
    } else if (entry.isFile) {
      await new Promise((res, rej) => {
        entry.file(file => {
          fs[entry.name] = file;
          res();
        }, rej);
      });
    }
    return fs;
  }
}

function readDropped(dT) {
  const entries = [...dT.items].map(item => {
      return item.webkitGetAsEntry ? item.webkitGetAsEntry() : null;
    })
    .filter(entry => entry);
  if (entries.length) {
    makedir(entries)
      .then(output)
      .catch(handleSecurityLimitation);
  } else notadir();

}

function notadir() {
  _log.textContent = "wasn't a directory, or webkitdirectory is not supported";
}

dropzone.ondragover = e => {
  e.preventDefault();
  dropzone.classList.add('over');
}
dropzone.ondragexit = dropzone.ondragend = e => dropzone.classList.remove('over');
dropzone.ondrop = e => {
  e.preventDefault();
  dropzone.classList.remove('over');
  readDropped(e.dataTransfer);
}

function output(system_trees) {
  console.log(system_trees);
  _log.textContent = JSON.stringify(system_trees, checkFile, 2);

  function checkFile(key, value) {
    if (value instanceof File) {
      return '{[File] ' + value.name + ', ' + value.size + 'b}';
    } else return value;
  }
}

function handleSecurityLimitation(error) {
  console.error(error);
  document.body.innerHTML = `
    <h2>Faced security limitations</h2>
    <a href="https://jsfiddle.net/x85vtnef/">Please go to this fiddle</a>`;
}
#dropzone {
  border: 1px solid;
  width: 90vw;
  height: 90vh;
  margin: 2vmin;
  padding: 2vmin;
  overflow: auto;
}

#dropzone.over {
  background-color: rgba(0, 0, 0, .2);
}
<div id="dropzone">
  Drop some directory here.
  <pre id="_log"></pre>
</div>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...