2010-08-28 12 views
52

No he visto ningún ejemplo que haga esto. ¿Esto no está permitido en la especificación api?¿HTML5 permite la carga de carpetas arrastradas o un árbol de carpetas?

Estoy buscando una solución fácil de arrastrar y soltar para cargar todo un árbol de carpetas de fotos.

+0

Lo mismo para 'input type = file': http: // stackoverflow .com/questions/9518335/select-directory-for-html5-multiple-file-input-in-firefox –

Respuesta

53

Ahora es posible, gracias a Chrome> = 21.

function traverseFileTree(item, path) { 
    path = path || ""; 
    if (item.isFile) { 
    // Get file 
    item.file(function(file) { 
     console.log("File:", path + file.name); 
    }); 
    } else if (item.isDirectory) { 
    // Get folder contents 
    var dirReader = item.createReader(); 
    dirReader.readEntries(function(entries) { 
     for (var i=0; i<entries.length; i++) { 
     traverseFileTree(entries[i], path + item.name + "/"); 
     } 
    }); 
    } 
} 

dropArea.addEventListener("drop", function(event) { 
    event.preventDefault(); 

    var items = event.dataTransfer.items; 
    for (var i=0; i<items.length; i++) { 
    // webkitGetAsEntry is where the magic happens 
    var item = items[i].webkitGetAsEntry(); 
    if (item) { 
     traverseFileTree(item); 
    } 
    } 
}, false); 

Más info: https://protonet.info/blog/html5-experiment-drag-drop-of-folders/

+7

Incluso 2 años después, IE y Firefox no parecen estar dispuestos a implementar esto. –

+0

pregunta sobre cómo usar en Chrome: http://stackoverflow.com/questions/5826286/how-do-i-use-google-chrome-11s-upload-folder-feature-in-my-own-code?lq = 1 –

+0

El enlace ya no funciona – frodo2975

13

En this message a la lista de correo HTML 5 Ian Hickson dice:

HTML5 ahora tiene que subir muchos archivos a la vez . Los navegadores pueden permitir a los usuarios elegir varios archivos a la vez, incluido en múltiples directorios; eso es un poco fuera del alcance de la especificación.

(Véase también el original feature proposal.) Por lo tanto, es seguro asumir que considera la posibilidad de subir carpetas usando arrastrar y soltar también fuera del ámbito. Aparentemente depende del navegador servir archivos individuales.

carpetas Carga también tendrían algunas otras dificultades, como se describe por Lars Gunther:

Esta [...] propuesta necesidad tienen dos cheques (si es factible en absoluto):

  1. Tamaño máximo, para evitar que alguien cargue un directorio completo de varias cientos de imágenes sin comprimir ...

  2. Filtrado incluso si se omite el atributo de aceptación. Los metadatos de Mac OS y las miniaturas de Windows, etc. deben ser omitidos. Todos los archivos ocultos y directorios deben estar predeterminados como excluidos.

+0

Hmmm, estoy de acuerdo con el punto 2 ... pero solo mientras haya una manera para que el desarrollador web determine si quieren habilitar la carga de archivos ocultos, ya que siempre existe la posibilidad de que un archivo oculto pueda ser operativo para el uso de la carpeta cargada. Especialmente si la carpeta está llena de documentos divididos en varias partes, como podría ser un archivo de corte final. –

+0

En desacuerdo con fuera del alcance: esta es una causa de incompatibilidades para algo que muchas personas desean hacer, por lo que debe especificarse. –

2

La especificación HTML 5 no dice que la hora de seleccionar una carpeta para la carga, el navegador debe cargar archivos de todos los contenidos de forma recursiva.

En realidad, en Chrome/Chromium, puede cargar una carpeta, pero cuando lo hace, solo carga un archivo de 4KB sin sentido, que representa el directorio. Algunas aplicaciones del lado del servidor como Alfresco pueden detectar esto, y advertir al usuario de que las carpetas no se pueden cargar:

The following cannot be uploaded because they are either folders or are zero bytes in size: undefined

+0

¿Un archivo inútil o un puntero a un archivo? – MoB

+0

@MoB: tal vez se trate de algún tipo de puntero. Pero dado que el archivo real está en la máquina del cliente, la máquina del servidor no podrá hacer nada con este puntero, por supuesto. –

8

Ahora puede cargar directorios con la función de arrastrar, soltar e ingresar.

<input type='file' webkitdirectory > 

y para arrastrar y soltar (Para navegadores webkit).

Manejo de arrastrar y soltar carpetas.

<div id="dropzone"></div> 
<script> 
var dropzone = document.getElementById('dropzone'); 
dropzone.ondrop = function(e) { 
    var length = e.dataTransfer.items.length; 
    for (var i = 0; i < length; i++) { 
    var entry = e.dataTransfer.items[i].webkitGetAsEntry(); 
    if (entry.isFile) { 
     ... // do whatever you want 
    } else if (entry.isDirectory) { 
     ... // do whatever you want 
    } 
    } 
}; 
</script> 

Recursos:

http://updates.html5rocks.com/2012/07/Drag-and-drop-a-folder-onto-Chrome-now-available

+1

¿Es posible hacer lo mismo para descargar sin usar carpetas comprimidas? – user2284570

1

¿Se HTML5 permiten arrastrar y soltar carpetas o carga de un árbol de carpetas?

Solo Chrome admite esta característica. No ha tenido tracción y es probable que se elimine.

Ref: https://developer.mozilla.org/en/docs/Web/API/DirectoryReader#readEntries

+0

Wow. Según la nota del W3C en ese enlace, esto no se continúa. ¿Cuál es la base de la suposición de que no ha logrado ninguna tracción? – bebbi

+0

@bebbi ningún otro proveedor de navegadores lo implementó – basarat

5

Firefox ahora soporta la subida de carpetas, el 15 de noviembre, 2016, en V50.0: https://developer.mozilla.org/en-US/Firefox/Releases/50#Files_and_directories

Puede arrastrar y soltar carpetas en Firefox o puede buscar y seleccionar un local de carpeta para cargar También admite carpetas anidadas en subcarpetas.

Eso significa que ahora puede usar Chrome, Firefox, Edge u Opera para cargar carpetas. No puede usar Safari o Internet Explorer en este momento.

3

Esta función le dará una promesa para el conjunto de todos los archivos se redujo, como <input type="file"/>.files:

function getFilesWebkitDataTransferItems(dataTransferItems) { 
    function traverseFileTreePromise(item, path='') { 
    return new Promise(resolve => { 
     if (item.isFile) { 
     item.file(file => { 
      file.filepath = path + file.name //save full path 
      files.push(file) 
      resolve(file) 
     }) 
     } else if (item.isDirectory) { 
     let dirReader = item.createReader() 
     dirReader.readEntries(entries => { 
      let entriesPromises = [] 
      for (let entr of entries) 
      entriesPromises.push(traverseFileTreePromise(entr, path + item.name + "/")) 
      resolve(Promise.all(entriesPromises)) 
     }) 
     } 
    }) 
    } 

    let files = [] 
    return new Promise((resolve, reject) => { 
    let entriesPromises = [] 
    for (let it of dataTransferItems) 
     entriesPromises.push(traverseFileTreePromise(it.webkitGetAsEntry())) 
    Promise.all(entriesPromises) 
     .then(entries => { 
     //console.log(entries) 
     resolve(files) 
     }) 
    }) 
} 

Uso:

dropArea.addEventListener("drop", function(event) { 
    event.preventDefault(); 

    var items = event.dataTransfer.items; 
    getFilesFromWebkitDataTransferItems(items) 
    .then(files => { 
     ... 
    }) 
}, false); 
+1

Esta debería ser la nueva respuesta aceptada. Es mejor que otras respuestas porque devuelve una promesa cuando se completa.Pero hubo algunos errores: 'function getFilesWebkitDataTransferItems (dataTransfer)' debe ser 'function getFilesWebkitDataTransferItems (items)', y 'for (entr of entries)' debe ser 'for (let entr entr entries)'. – RoccoB

Cuestiones relacionadas