在JavaScript中上传文件夹及其所有内容

时间:2017-02-15 02:26:28

标签: javascript

如何使用JavaScript(客户端)上传文件夹的内容? Chrome以外的浏览器尚未采用FileSystem API;我只得到一个带有文件夹名称的文件项。

应该可以,因为Google云端硬盘允许删除文件夹,所有内容(文件夹和文件)都会自动上传。

6 个答案:

答案 0 :(得分:5)

您实际上可以在所有最新版本的Chrome,Firefox和Microsoft Edge中上传目录。有许多工作示例可供查看。

这是我之前在项目中使用过的一个很好的工作示例

Quarklemotion Html5FileSelector

此外,Dropzone JS也支持目录上传,并且可以在Chrome,FF和Edge中使用。我刚刚在自己的项目中过渡到使用它。

Dropzone JS

这些解决方案递归地读取目录条目并列出所有文件,包括它们的相对路径。如果要在上载时重建文件夹结构,则必须使用相对路径和相应的算法来实现它。

答案 1 :(得分:4)

我已经使用webkit作了一个完整的例子。

纯Javascript,HTML和PHP,无需任何其他库。

可以免费下载或克隆我的仓库。

https://github.com/komputronika/UploadFolder

enter image description here

答案 2 :(得分:2)

Chrome和Firefox似乎支持部分文件系统API,但并未正式支持。

这允许您删除文件夹并读取所有内容,这是我在应用程序上使用的代码。

    function add Files(e){
        e.stopPropagation();
        e.preventDefault();

        // if directory support is available
        if(e.dataTransfer && e.dataTransfer.items)
        {
            var items = e.dataTransfer.items;
            for (var i=0; i<items.length; i++) {
                var item = items[i].webkitGetAsEntry();

                if (item) {
                  addDirectory(item);
                }
            }
            return;
        }

        // Fallback
        var files = e.target.files || e.dataTransfer.files;
        if (!files.length)
        {
            alert('File type not accepted');
            return;
        }

        processFile(files);
    }

    function addDirectory(item) {
        var _this = this;
        if (item.isDirectory) {
            var directoryReader = item.createReader();
            directoryReader.readEntries(function(entries) {
            entries.forEach(function(entry) {
                    _this.addDirectory(entry);
                });
            });
        } else {
            item.file(function(file){
                processFile([file],0);
            });
        }
    },

答案 3 :(得分:0)

不幸的是,目前只有基于webkit的浏览器支持文件系统API。

如果您尝试使用firefox或Internet Explorer在Google云端硬盘中删除某个文件夹,则会收到一条错误消息,指出它不受支持。

答案 4 :(得分:0)

如果可以使用非标准属性,则可以使用webkitdirectory属性:

let picker = document.getElementById('picker');

picker.addEventListener('change', e => {
  for (let file of Array.from(e.target.files)) {
    alert(`File located at ${file.webkitRelativePath}`);
  };
});

Demo

答案 5 :(得分:0)

  • 要实现文件夹上传,您需要同时应用JS端和服务器端:
  • 在JS端,我使用以下方法(来自StackoverFlow上的老师-https://stackoverflow.com/a/47935286/11544097)来循环和归档所有文件,文件夹内容和子文件夹:

    function makedir(entries){       const systems = entry.map(entry => traverse(entry,{}));       返回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 checkFile(obj){
        return obj instanceof File;
    };
    
    function exactFile(system_trees, relativePath, files){
        for (var i = 0; i < system_trees.length; i++){
            for (var property in system_trees[i]) {
                if (system_trees[i].hasOwnProperty(property)) {
                    if (checkFile(system_trees[i][property])){
                        system_trees[i][property]["relativePath"] = relativePath;
                        files.push(system_trees[i][property]);
                    } else {
                        files.concat(exactFile([system_trees[i][property]], (typeof relativePath !== 'undefined' && relativePath !== '' ? (relativePath + '/') : '') + property, files));
                    }
                }
            }
        }
        return files;
    };
    
    function readDropped(dT,_data) {
      const entries = [...dT.items].map(item => {
          return item.webkitGetAsEntry ? item.webkitGetAsEntry() : null;
        })
        .filter(entry => entry);
      if (entries.length) {
        makedir(entries).then(function(system_trees){
            var files = exactFile(system_trees, "", []);
            c(_data, files);
        }).catch(function(){
            var files = dT.files;
            c(_data, files);
        });
      } else {
            var files = dT.files;
            c(_data, files);
      }
    };
    
  • “ dT”是 drop 事件(e.originalEvent.dataTransfer)和“ _data”是Ajax上传提交表单。
  • 您还需要一个上传库或自己编写,以通过ajax上传发送到文件到服务器。在上面的代码示例中,我使用了Formstone上传库(https://formstone.it/components/upload/

  • 在服务器端:您需要处理从JS端发送的表单数据,大多数情况下,您需要使用文件对象中包含的相对路径信息逐个文件地处理文件。

  • 还有一点要注意,只需在文件上传输入处设置“ multiple”属性,就不需要“ webkitdirectory”或“ directory”。它们导致用户无法选择文件(仅允许文件夹)

  • 结果将使您的上传系统支持所有文件夹,文件将保持其结构,如Google Drive:)。

  • 我已经编写了一种工具(https://freetoolonline.com/zip-file.html),该工具基于上面已经解释过的理想支持文件夹上传。