¿Cómo establecer el valor de entrada de archivo al soltar el archivo en la página? [duplicar]


Esta pregunta ya tiene una respuesta aquí:

Estoy tratando de hacer un control donde ambos pueden seleccionar un archivo para enviar en el formulario y soltar un archivo en él para hacer lo mismo. Tengo algo como esto donde también mostrará una vista previa del archivo si es una imagen:

<div class="preview-image-container">

  <input type="file" name="File" id="File" accept="image/*" 
         class="image-url form-control" style="display:none;" />

  <div class="preview-image-dummy"></div><img class="preview-image-url" />
  <div class="preview-image-instruction">
    <div class="preview-image-btn-browse btn btn-primary">Select file</div>
    <p>or drop it here.</p>
  </div>

</div>

He aquí un violín con MCVE .

El usuario deja caer el archivo en el preview-image-container. El archivo no se envía con AJAX, el usuario debe enviar el formulario que contiene más datos.

Por razones de seguridad, no se nos permite cambiar el valor del archivo de entrada con JavaScript. Sin embargo, sé que el soporte de archivo de entrada predeterminado es droppable y hay un montón de sitios web que nos permiten seleccionar archivos soltándolos en el formulario, por lo que mi conjetura es que hay una manera de hacerlo.

Como puede ver en MCVE, solo estoy interesado en usar jQuery o JavaScript puro sin bibliotecas adicionales.

Aunque dropzone.js podría ser usado, no encaja en mis requisitos y requeriría una cantidad de tiempo considerada para personalizar su aspecto. Además, dropzone.js tienen ciertos requisitos de configuración que no se pueden cumplir dentro de mi ASP.NET solicitud.


Hay una pregunta similar pero no tiene una respuesta adecuada:
¿Cómo establecer un objeto de archivo en un archivo de entrada en el formulario en HTML?

Tampoco es similar a arrastrar y soltar el archivo de entrada de imágenes y previsualizar antes de cargar porque ya han logrado arrastrar y soltar y previsualizar la acción. Mi pregunta es específica al problema de tener una entrada de archivo vacía al soltar el archivo en un contenedor padre.

Author: Samuel Liew, 2017-11-27

1 answers

Descargo de responsabilidad: Correcto a partir de diciembre de 2017 y solo para navegadores modernos.


TL; DR: ¡Sí, ahora puedes!

*si tiene un objeto DataTransfer o FileList

Anteriormente , el cambio programático del campo files input[type=file] estaba deshabilitado debido a vulnerabilidades de seguridad heredadas, que se corrigen en los navegadores modernos.

El último de los principales navegadores (Firefox), nos ha permitido recientemente establecer los archivos para el campo archivo de entrada. De acuerdo con Pruebas W3C, parece que ya se puede hacer esto en Google Chrome!

Captura de pantalla relevante y texto citado de MDN:

introduzca la descripción de la imagen aquí

Puede set así como obtener el valor de HTMLInputElement.files en todos los navegadores modernos.
Compatibilidad con el origen y el navegador, consulte MDN

El hilo de discusión de corrección de errores de Firefox tiene esto demostración que puede probar lo que pasa, y aquí está la fuente si quieres editarla. Para referencia futura en caso de que este enlace muera, también lo incluiré como un fragmento ejecutable a continuación:

let target = document.documentElement;
let body = document.body;
let fileInput = document.querySelector('input');

target.addEventListener('dragover', (e) => {
  e.preventDefault();
  body.classList.add('dragging');
});

target.addEventListener('dragleave', () => {
  body.classList.remove('dragging');
});

target.addEventListener('drop', (e) => {
  e.preventDefault();
  body.classList.remove('dragging');
  
  fileInput.files = e.dataTransfer.files;
});
body {
  font-family: Roboto, sans-serif;
}

body.dragging::before {
  content: "Drop the file(s) anywhere on this page";
  position: fixed;
  left: 0; width: 100%;
  top: 0; height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 1.5em;
  background-color: rgba(255, 255, 0, .3);
  pointer-events: none;
}

button, input {
  font-family: inherit;
}

a {
  color: blue;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
      <link href="https://fonts.googleapis.com/css?family=Roboto:400,400i,700" rel="stylesheet"> 

  <title>JS Bin</title>
</head>
<body>
  
  <h1>Drag and drop files into file input</h1>
  
  <p><small>Supported in <a href="https://github.com/whatwg/html/issues/2861">WebKit and Blink</a>. To test, drag and drop one or more files from your operating system onto this page.</small></p>
  
  <p>
    <input type="file">
  </p>

</body>
</html>

Nota Importante:

Solo puede hacer esto si tiene un objeto FileList O dataTransfer existente que puede establecer en el elemento input file (ya que el método setter NO acepta cadenas de texto sin formato).

Para más información, véase La respuesta de Kaiido aquí: ¿Cómo establecer los objetos de archivo y la propiedad length en el objeto FileList donde los archivos también se reflejan en el objeto FormData?


Ahora para responder a su pregunta original, debería ser tan simple como esto: {[74]]}
document.querySelector('.preview-image-instruction')
    .addEventListener('drop', (ev) => {
        ev.preventDefault();
        document.querySelector('.image-url').files = ev.dataTransfer.files;
    });

 38
Author: Samuel Liew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-07 00:32:55