headers attribute html5 file-upload drag-and-drop

html5 - attribute - arrastre los archivos de la gota a la entrada estándar del archivo html



headers html (10)

En estos días podemos arrastrar y soltar archivos en un contenedor especial y subirlos con XHR 2. Muchos a la vez. Con barras de progreso en vivo, etc. Cosas muy interesantes. Ejemplo aquí.

Pero a veces no queremos tanta frialdad. Lo que me gustaría es arrastrar y soltar archivos, muchos a la vez, en una entrada de archivo HTML estándar : <input type=file multiple> .

¿Es eso posible? ¿Hay alguna forma de ''completar'' la entrada del archivo con los nombres de archivo correctos (?) Del archivo desplegado? (Los filepaths completos no están disponibles por razones de seguridad del sistema de archivos).

¿Por qué? Porque me gustaría enviar un formulario normal. Para todos los navegadores y todos los dispositivos. La función de arrastrar y soltar es solo una mejora progresiva para mejorar y simplificar UX. El formulario estándar con entrada de archivo estándar (+ atributo multiple ) estará allí. Me gustaría agregar la mejora HTML5.

editar
Sé que en algunos navegadores a veces puedes (casi siempre) colocar archivos en la entrada del archivo. Sé que Chrome generalmente hace esto, pero a veces falla y luego carga el archivo en la página actual (un gran error si estás completando un formulario). Quiero engañar- y a prueba de navegador.


En teoría, podría agregar un elemento que superponga a <input/> , y luego usar su evento drop para capturar los archivos (usando File API) y pasarlos a la matriz de files entrada.

Excepto que una entrada de archivo es de solo lectura . Este es un viejo problema.

Sin embargo, puede omitir el control de formulario por completo y cargarlo a través de XHR (no estoy seguro del soporte para eso):

También puede usar un elemento en el área circundante para cancelar el evento de soltar en Chrome y evitar el comportamiento predeterminado de cargar el archivo.

Dejar caer varios archivos sobre la entrada ya funciona en Safari y Firefox.


Esta es la forma HTML5 de "DTHML" para hacerlo. Entrada de forma normal (que se lee solo como señaló Ricardo Tomasi). Luego, si se arrastra un archivo, se adjunta al formulario. Esto REQUERIRÁ la modificación de la página de acción para aceptar el archivo cargado de esta manera.

function readfiles(files) { for (var i = 0; i < files.length; i++) { document.getElementById(''fileDragName'').value = files[i].name document.getElementById(''fileDragSize'').value = files[i].size document.getElementById(''fileDragType'').value = files[i].type reader = new FileReader(); reader.onload = function(event) { document.getElementById(''fileDragData'').value = event.target.result;} reader.readAsDataURL(files[i]); } } var holder = document.getElementById(''holder''); holder.ondragover = function () { this.className = ''hover''; return false; }; holder.ondragend = function () { this.className = ''''; return false; }; holder.ondrop = function (e) { this.className = ''''; e.preventDefault(); readfiles(e.dataTransfer.files); }

#holder.hover { border: 10px dashed #0c0 !important; }

<form method="post" action="http://example.com/"> <input type="file"><input id="fileDragName"><input id="fileDragSize"><input id="fileDragType"><input id="fileDragData"> <div id="holder" style="width:200px; height:200px; border: 10px dashed #ccc"></div> </form>

Es aún más importante si puede hacer que toda la ventana sea una zona de colocación, consulte ¿Cómo puedo detectar un evento de arrastrar HTML5 que ingresa y sale de la ventana, como lo hace Gmail?


Hice una solución para esto.

$(function () { var dropZoneId = "drop-zone"; var buttonId = "clickHere"; var mouseOverClass = "mouse-over"; var dropZone = $("#" + dropZoneId); var ooleft = dropZone.offset().left; var ooright = dropZone.outerWidth() + ooleft; var ootop = dropZone.offset().top; var oobottom = dropZone.outerHeight() + ootop; var inputFile = dropZone.find("input"); document.getElementById(dropZoneId).addEventListener("dragover", function (e) { e.preventDefault(); e.stopPropagation(); dropZone.addClass(mouseOverClass); var x = e.pageX; var y = e.pageY; if (!(x < ooleft || x > ooright || y < ootop || y > oobottom)) { inputFile.offset({ top: y - 15, left: x - 100 }); } else { inputFile.offset({ top: -400, left: -400 }); } }, true); if (buttonId != "") { var clickZone = $("#" + buttonId); var oleft = clickZone.offset().left; var oright = clickZone.outerWidth() + oleft; var otop = clickZone.offset().top; var obottom = clickZone.outerHeight() + otop; $("#" + buttonId).mousemove(function (e) { var x = e.pageX; var y = e.pageY; if (!(x < oleft || x > oright || y < otop || y > obottom)) { inputFile.offset({ top: y - 15, left: x - 160 }); } else { inputFile.offset({ top: -400, left: -400 }); } }); } document.getElementById(dropZoneId).addEventListener("drop", function (e) { $("#" + dropZoneId).removeClass(mouseOverClass); }, true); })

#drop-zone { /*Sort of important*/ width: 300px; /*Sort of important*/ height: 200px; position:absolute; left:50%; top:100px; margin-left:-150px; border: 2px dashed rgba(0,0,0,.3); border-radius: 20px; font-family: Arial; text-align: center; position: relative; line-height: 180px; font-size: 20px; color: rgba(0,0,0,.3); } #drop-zone input { /*Important*/ position: absolute; /*Important*/ cursor: pointer; left: 0px; top: 0px; /*Important This is only comment out for demonstration purposes. opacity:0; */ } /*Important*/ #drop-zone.mouse-over { border: 2px dashed rgba(0,0,0,.5); color: rgba(0,0,0,.5); } /*If you dont want the button*/ #clickHere { position: absolute; cursor: pointer; left: 50%; top: 50%; margin-left: -50px; margin-top: 20px; line-height: 26px; color: white; font-size: 12px; width: 100px; height: 26px; border-radius: 4px; background-color: #3b85c3; } #clickHere:hover { background-color: #4499DD; }

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <div id="drop-zone"> Drop files here... <div id="clickHere"> or click here.. <input type="file" name="file" id="file" /> </div> </div>

La funcionalidad de arrastrar y soltar para este método solo funciona con Chrome, Firefox y Safari. (No sé si funciona con IE10), pero para otros navegadores, el botón "O hacer clic aquí" funciona bien.

El campo de entrada simplemente sigue el mouse al arrastrar un archivo sobre un área y también he agregado un botón.

Opacidad de comentario: 0; la entrada del archivo solo está visible para que pueda ver lo que está sucediendo.


Impresionante trabajo de @BjarkeCK. Hice algunas modificaciones a su trabajo, para usarlo como método en jquery:

$.fn.dropZone = function() { var buttonId = "clickHere"; var mouseOverClass = "mouse-over"; var dropZone = this[0]; var $dropZone = $(dropZone); var ooleft = $dropZone.offset().left; var ooright = $dropZone.outerWidth() + ooleft; var ootop = $dropZone.offset().top; var oobottom = $dropZone.outerHeight() + ootop; var inputFile = $dropZone.find("input[type=''file'']"); dropZone.addEventListener("dragleave", function() { this.classList.remove(mouseOverClass); }); dropZone.addEventListener("dragover", function(e) { console.dir(e); e.preventDefault(); e.stopPropagation(); this.classList.add(mouseOverClass); var x = e.pageX; var y = e.pageY; if (!(x < ooleft || x > ooright || y < ootop || y > oobottom)) { inputFile.offset({ top: y - 15, left: x - 100 }); } else { inputFile.offset({ top: -400, left: -400 }); } }, true); dropZone.addEventListener("drop", function(e) { this.classList.remove(mouseOverClass); }, true); } $(''#drop-zone'').dropZone();

Fiddle de trabajo


Lo que podría hacer es mostrar una entrada de archivo y superponerla con su área de colocación transparente, teniendo cuidado de usar un nombre como file[1] . {Asegúrese de tener el enctype="multipart/form-data" dentro de su etiqueta FORM.}

Luego haga que el área desplegable maneje los archivos adicionales creando dinámicamente más entradas de archivo para los archivos 2..number_of_files, asegúrese de usar el mismo nombre base, llenando el valor-atributo de manera apropiada.

Por último (front-end) envíe el formulario.

Todo lo que se requiere para manejar este método es alterar su procedimiento para manejar una matriz de archivos.


Lo siguiente funciona en Chrome y FF, pero todavía no he encontrado una solución que cubra IE10 +:

// dragover and dragenter events need to have ''preventDefault'' called // in order for the ''drop'' event to register. // See: https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Drag_operations#droptargets dropContainer.ondragover = dropContainer.ondragenter = function(evt) { evt.preventDefault(); }; dropContainer.ondrop = function(evt) { // pretty simple -- but not for IE :( fileInput.files = evt.dataTransfer.files; evt.preventDefault(); };

<!DOCTYPE html> <html> <body> <div id="dropContainer" style="border:1px solid black;height:100px;"> Drop Here </div> Should update here: <input type="file" id="fileInput" /> </body> </html>

Probablemente quiera usar addEventListener o jQuery (etc.) para registrar sus manejadores de evt, esto solo por el bien de la brevedad.


Para una solución de solo CSS:

<div class="file-area"> <input type="file"> <div class="file-dummy"> <span class="default">Click to select a file, or drag it here</span> <span class="success">Great, your file is selected</span> </div> </div> .file-area { width: 100%; position: relative; font-size: 18px; } .file-area input[type=file] { position: absolute; width: 100%; height: 100%; top: 0; left: 0; right: 0; bottom: 0; opacity: 0; cursor: pointer; } .file-area .file-dummy { width: 100%; padding: 50px 30px; border: 2px dashed #ccc; background-color: #fff; text-align: center; transition: background 0.3s ease-in-out; } .file-area .file-dummy .success { display: none; } .file-area:hover .file-dummy { border: 2px dashed #1abc9c; } .file-area input[type=file]:valid + .file-dummy { border-color: #1abc9c; } .file-area input[type=file]:valid + .file-dummy .success { display: inline-block; } .file-area input[type=file]:valid + .file-dummy .default { display: none; }

Modificado de https://codepen.io/Scribblerockerz/pen/qdWzJw


Pocos años después, construí esta biblioteca para hacer caer los archivos en cualquier elemento HTML.

Puedes usarlo como

const Droppable = require(''droppable''); const droppable = new Droppable({ element: document.querySelector(''#my-droppable-element'') }) droppable.onFilesDropped((files) => { console.log(''Files were dropped:'', files); }); // Clean up when you''re done! droppable.destroy();


Sé que algunos trucos funcionan en Chrome.

Cuando coloca un archivo en la zona de colocación, obtiene un objeto dataTransfer.files, que es un tipo de objeto "FileList" que contiene todos los archivos que arrastró. Mientras tanto, el elemento tiene "archivos" de propiedades, que es el mismo objeto tipo "FileList".

Por lo tanto, puede simplemente asignar el objeto dataTransfer.files a la propiedad input.files.


//----------App.js---------------------// $(document).ready(function() { var holder = document.getElementById(''holder''); holder.ondragover = function () { this.className = ''hover''; return false; }; holder.ondrop = function (e) { this.className = ''hidden''; e.preventDefault(); var file = e.dataTransfer.files[0]; var reader = new FileReader(); reader.onload = function (event) { document.getElementById(''image_droped'').className=''visible'' $(''#image_droped'').attr(''src'', event.target.result); } reader.readAsDataURL(file); }; });

.holder_default { width:500px; height:180px; border: 10px dashed #ccc; } #holder.hover { width:400px; height:180px; border: 10px dashed #0c0 !important; } .hidden { visibility: hidden; } .visible { visibility: visible; }

<!DOCTYPE html> <html> <head> <title> HTML 5 </title> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.js"></script> </head> <body> <form method="post" action="http://example.com/"> <div id="holder" style="" id="holder" class="holder_default"> <img src="" id="image_droped" width="500" height="180" style="width:500px; height:180px; border: 10px dashed #7A97FC;" class=" hidden"/> </div> </form> </body> </html>