2016-09-06 6 views
2

Я хочу загрузить папку на сервер d''d через AJAX. Но уже, у меня проблемы с загрузкой файлов.Как передавать файлы (или папки) через Ajax by d'n'd?

Я использую e.dataTransfer.items и webkitGetAsEntry(), чтобы проверить - это файл или папка?

Если это файл, в функции traverseFileTree я получаю файл, но я не могу добавить его formData.

Если я использую e.dataTransfer.files, я не знаю, что это. Файл или папка, потому что webkitGetAsEntry() получить ошибку.

Что я делаю неправильно? Как передать файлы в глобальный массив $ _FILES.

Источник (upload.php):

echo "<pre>"; 
print_r ($_FILES); 
echo "</pre>"; 

Источник (index.html):

<!DOCTYPE html> 
<html> 
<head> 
<title>Drag and Drop</title> 
<style> 
body { 
    background: rgba(211,211,100, .5); 
    font: 20px Arial; 
} 

.dropzone { 
    width: 300px; 
    height: 300px; 
    border: 2px dashed #aaa; 
    color: #aaa; 
    line-height: 280px; 
    text-align: center; 
    position: absolute; 
    left: 50%; 
    margin-left: -150px; 
    top: 50%; 
    margin-top: -150px; 
} 

.dropzone.dragover { 
    color: green; 
    border: 2px dashed #000; 
} 
</style> 
</head> 
<body> 
<p>Loaded files:</p> 
<div id="uploads"> 
    <ul> 

    </ul> 
</div> 
<div class="dropzone" id="dropzone">Drop files</div> 
<script> 

(function() { 
    var formData = new FormData(); 
    var dropzone = document.getElementById("dropzone"); 

    dropzone.ondrop = function(e) { 
     this.className = 'dropzone'; 
     this.innerHTML = 'Drop files'; 
     e.preventDefault(); 
     upload(e.dataTransfer.items); 
    }; 

    function traverseFileTree(item, path) { 
     path = path || ""; 
     if (item.isFile) { 
      item.file(function(file) { 
       console.log(file);     // show info 
       formData.append('file[]', file); // file exist, but don't append 
      }); 
     } /*else if (item.isDirectory) { 
      var dirReader = item.createReader(); 
      dirReader.readEntries(function(entries) { 
       for (var i=0; i<entries.length; i++) { 
        traverseFileTree(entries[i], path + item.name + "/"); 
       } 
      }); 
     }*/ 
    } 


    var upload = function(items) { 
     var xhr = new XMLHttpRequest(); 

     for(var i = 0; i < items.length; i++) { 
      var item = items[i].webkitGetAsEntry(); 
      if (item) { 
       traverseFileTree(item,''); 
      } 
     } 

     xhr.onload = function() { 
      console.log(this.responseText); 
     }; 

     xhr.open('post', 'upload.php'); 
     xhr.send(formData); 
    }; 

    dropzone.ondragover = function() { 
     this.className = 'dropzone dragover'; 
     this.innerHTML = 'Mouse up'; 
     return false; 
    }; 

    dropzone.ondragleave = function() { 
     this.className = 'dropzone'; 
     this.innerHTML = 'Drop files'; 
     return false; 
    }; 

})(); 
</script> 

+0

так, вы только хотите, чтобы это работало на хром и другие браузеры на основе WebKit? –

+0

@JaromandaX firefox поддерживает загрузку папок, см. [Выбор и удаление файлов и/или папок для разбора] (http://stackoverflow.com/questions/36842425/select-drop-files-and-or-folders-to-be -parsed /) – guest271314

+0

@JaromandaX да, я хочу, чтобы он работал в хроме .... Мне все равно. Я просто хочу, чтобы он работал. Я не могу решить это несколько дней, моя неделя. Я хочу сделать что-то вроде dropBox. Пользователь может удалить папку. –

ответ

1

Оба file() и readEntries() возвращают результаты асинхронно. Поскольку невозможно точно знать, сколько файлов или каталогов, которые сами могут содержать дополнительные каталоги, содержащие еще больше файлов или папок, будут выбраны и удалены пользователем, один или рекурсивный вызов traverseFileTree потребует определенного механизма для определения того, когда все асинхронные операции завершены. Это может быть достигнуто с использованием одного или нескольких из нескольких подходов.

Настоящий подход увеличивает значение переменной n, подталкивает каждый отдельный файл к массиву uploads. Если n - 0, обработайте первый файл; приращение n так, что его значение 1 больше, чем массив, не содержащий файлы .length до массива .length равно n - 1

uploads.length === n - 1 || n === 0 

затем скопировать uploads массив с помощью .slice(), установите uploads.length и n к 0, передать массив файлов функционировать processFiles где файлы добавляются к объекту FormData(), вызывается XMLHttpRequest().

<!DOCTYPE html> 
<html> 

<head> 
    <title>Drag and Drop</title> 
    <style> 
    body { 
     background: rgba(211, 211, 100, .5); 
     font: 20px Arial; 
    } 

    .dropzone { 
     width: 300px; 
     height: 300px; 
     border: 2px dashed #aaa; 
     color: #aaa; 
     line-height: 280px; 
     text-align: center; 
     position: absolute; 
     left: 50%; 
     margin-left: -150px; 
     top: 50%; 
     margin-top: -150px; 
    } 

    .dropzone.dragover { 
     color: green; 
     border: 2px dashed #000; 
    } 
    </style> 
</head> 

<body> 
    <p>Loaded files:</p> 
    <div id="uploads"> 
    <ul> 

    </ul> 
    </div> 
    <div class="dropzone" id="dropzone">Drop files</div> 
    <script> 
    (function() { 
     var n = 0, uploads = []; 

     var dropzone = document.getElementById("dropzone"); 

     dropzone.ondrop = function(e) { 
     this.className = 'dropzone'; 
     this.innerHTML = 'Drop files'; 
     e.preventDefault(); 
     upload(e.dataTransfer.items); 

     }; 

     function processFiles(files) { 
     console.log("files:", files); 
     alert("processing " + files.length + " files"); 
     var formData = new FormData(); 
     // append files to `formData` 
     for (file of files) { 
      formData.append("file[]", file, file.name) 
     } 
     // check `formData` entries 
     var curr = 0; 
     for (data of formData.entries()) { 
      console.log("formData entry " + curr, data); 
      ++curr; 
     } 
     delete curr; 
     // do ajax stuff here 
     var xhr = new XMLHttpRequest(); 
     xhr.onload = function() { 
     console.log(this.responseText); 
     }; 

     xhr.open("POST", "upload.php"); 
     xhr.send(formData); 
     } 

     function traverseFileTree(item, path) { 

     var handleFiles = function handleFiles(item, path) { 
      path = path || ""; 
      if (item.isFile) { 
      item.file(function(file) { 
       uploads.push(file); 
       console.log(file, n, uploads.length); // show info 
       if (uploads.length === n - 1 || n === 0) { 
       alert("traverseFiles complete, uploads length: " 
         + uploads.length); 
       var files = uploads.slice(0); 
       n = uploads.length = 0; 
       processFiles(files) 
       } 
      }); 
      } else if (item.isDirectory) { 
      var dirReader = item.createReader(); 
      dirReader.readEntries(function(entries) { 
       // increment `n` here 
       n += entries.length; 
       for (var i = 0; i < entries.length; i++) { 
       handleFiles(entries[i], path + item.name + "/"); 
       } 
      }); 
      } 
     } 

     handleFiles(item, path); 

     } 

     var upload = function(items) { 

     if (n !== 0 && uploads.length !== 0) { 
      n = uploads.length = 0; 
     } 

     for (var i = 0; i < items.length; i++) { 
      var item = items[i].webkitGetAsEntry(); 
      if (item) { 
      traverseFileTree(item, ""); 
      } 
     } 

     }; 

     dropzone.ondragover = function() { 
     this.className = 'dropzone dragover'; 
     this.innerHTML = 'Mouse up'; 
     return false; 
     }; 

     dropzone.ondragleave = function() { 
     this.className = 'dropzone'; 
     this.innerHTML = 'Drop files'; 
     return false; 
     }; 

    })(); 
    </script> 
</body> 
</html> 

plnkr http://plnkr.co/edit/OdFrwYH2gmbtvHfq3ZjH?p=preview


Смотрите также How can I filter out directories from upload handler in Firefox?, How to read files from folder

+1

Спасибо вам большое! Полезно и работоспособно Однако у меня есть некоторые непонятные моменты. Возможно, в конце концов я понимаю, почему так. Прошу прощения, я так долго не отвечал и благодарю за подробный ответ! Немного изменил код, вот результат: [codepen.io] (http://codepen.io/work_forfood/pen/bwVWXL) –