Uploading directory and maintainign structure through JavaScript and HTML5












0














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)?










share|improve this question



























    0














    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)?










    share|improve this question

























      0












      0








      0







      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)?










      share|improve this question













      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)?







      javascript html5






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Dec 21 '17 at 20:55









      mjabraham

      493618




      493618
























          1 Answer
          1






          active

          oldest

          votes


















          1














          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>





          And as fiddle for chrome





          *chrome code (extensions and plugins) generally already have access to a FileSystem API.
          *"webkit-API" here means experimental, i.e which behavior may change any time and may not be the same on every browsers.






          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f47932586%2fuploading-directory-and-maintainign-structure-through-javascript-and-html5%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            1














            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>





            And as fiddle for chrome





            *chrome code (extensions and plugins) generally already have access to a FileSystem API.
            *"webkit-API" here means experimental, i.e which behavior may change any time and may not be the same on every browsers.






            share|improve this answer




























              1














              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>





              And as fiddle for chrome





              *chrome code (extensions and plugins) generally already have access to a FileSystem API.
              *"webkit-API" here means experimental, i.e which behavior may change any time and may not be the same on every browsers.






              share|improve this answer


























                1












                1








                1






                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>





                And as fiddle for chrome





                *chrome code (extensions and plugins) generally already have access to a FileSystem API.
                *"webkit-API" here means experimental, i.e which behavior may change any time and may not be the same on every browsers.






                share|improve this 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>





                And as fiddle for chrome





                *chrome code (extensions and plugins) generally already have access to a FileSystem API.
                *"webkit-API" here means experimental, i.e which behavior may change any time and may not be the same on every browsers.






                /* 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>





                /* 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>






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Dec 27 '17 at 5:38

























                answered Dec 22 '17 at 2:51









                Kaiido

                38.9k45799




                38.9k45799






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f47932586%2fuploading-directory-and-maintainign-structure-through-javascript-and-html5%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Full-time equivalent

                    Bicuculline

                    さくらももこ