Foro de elhacker.net

Programación => Desarrollo Web => Mensaje iniciado por: .:Xx4NG3LxX:. en 20 Julio 2020, 07:10



Título: [HTML][javascript] Dar vista previa de un input de tipo file o image...
Publicado por: .:Xx4NG3LxX:. en 20 Julio 2020, 07:10
Saludos,

Bueno, creo que el título es un bien resume, pero ahí les va mi explicación:



1.- Crear un html (super basico) con algo así:
Código
  1. <!-- Arriba lo demás -->
  2.  
  3. <input type="file" id="imagen" onChange="funcion()" />
  4. <input type="button" onClick="otra_funcion()" />
  5. <br /><div id="previsualizacion"><!-- Aquí se verá la imagen --></div>
  6.  
  7. <!-- Abajo lo demás -->

2.- En el javascript quiero que haga algún tipo de proceso, para ver que el archivo sea de imagen (png, jpg, bmp, gif, etc...) Y eso es lo que no sé hacer..

Agradezco cualquier guía que me den, he visto ya algunos ejemplos en la web, pero no término de entenderlos...

PD: Quisiera hacerlo solo con javascript sin incluir JQuery u otra librería.
PostPD: El código HTML que puse de ejemplo; probablemente falten atributos, lo hice rápido para mostrar la idea.


Título: Re: [HTML][javascript] Dar vista previa de un input de tipo file o image...
Publicado por: @XSStringManolo en 20 Julio 2020, 14:32
Para saber si es una imagen o lo que, o miras el mime type (primeros bytes binarios del archivo) que siempre debería ser los mismos o intentas visualizar el formato dando por echo de antemano que es una imagen.
https://github.com/StringManolo/JEX/blob/master/jexLastVersion.html#L194

Aquí hice un listado de los bytes binarios. Está en hexadecimal porque ocupa menos y se reconocen mejor.

El código que te pasé es un string de cabeceras separadas por coma. Al final del string le aplico el método toUpperCase() para pasarlo a mayúsculas
 Más alante hago split por las comas de tal forma que obtengo un array con 156 elementos que contienen 156 cadenas hexadecimales.

En la línea 216 https://github.com/StringManolo/JEX/blob/master/jexLastVersion.html#L216 tienes lo mismo pero esta vez son las extensiones/nombre de formatos de los archivos.

En la línea 235
https://github.com/StringManolo/JEX/blob/master/jexLastVersion.html#L235
hay una llamada a
Código
  1. CompareMagicN(header, magicN[k])
donde se compara en un bucle cada elemento del array de números mágicos con la cabecera del archivo.

Si CompareMagicN encuentra una coincidencia de numeros mágicos se obtiene la extensión equivalente con var tipoDelArchivo = typeN[k];

Tienes la función definida en la línea 185
https://github.com/StringManolo/JEX/blob/master/jexLastVersion.html#L185 Solo es comparar los caracteres de la header con los caracteres de cada elemento de typeN

Por último, definí la función para leer el archivo en la línea 98
https://github.com/StringManolo/JEX/blob/master/jexLastVersion.html#L98
IMPORTANTE: Tu deberías leer solo los 32 primeros caracteres en hexadecimal, no tiene sentido leer todo el archivo para determinar el tipo a menos que programes un binwalk o algo por el estilo.

Si solo vas a trabajar con imágenes, puedes usar el canvas para leer los magic number, va a ser más eficiente.

CONSIDERACIONES:
Si esta comprobación es parte de una aplicación que enviará datos al backend recuerda que nunca se debe creer lo que mande el cliente.

La eficiencia del navegador es nula si trabajas con archivos muy grandes como puedan ser imágenes RAW de una cámara. En este caso tendrás que implementar lógica en el back-end ya sea para adecuar el tamaño en bytes del archivo o procesarla en el back-end. Una solución 100% navegador es programarlo en C/C++ y cross compilarlo a WebAssembler, cargar el módulo y llamar la función.

Si tu aplicación no va a ser stateless, incluir javascript inline impide que puedas utilizar normas restrictivas como CSP para hacer tu aplicación más segura. Deberías entonces mover todo el javascript y css a otros archivos.


Título: Re: [HTML][javascript] Dar vista previa de un input de tipo file o image...
Publicado por: EdePC en 20 Julio 2020, 16:39
Wow, si quieres una solución menos traumática podrías pecar de confiado para con el usuario, es decir, usar simple javascript, Html y CSS:

Código
  1. <style>
  2.  #imagen { display: block; width: 100%; }
  3. </style>
  4.  
  5. <input type="file" accept="image/png,image/jpeg" onchange="cargaImagen()">
  6. <img id="imagen">
  7.  
  8. <script>
  9.  function cargaImagen() {
  10.    var Imagen = event.target.files[0]
  11.    console.log(Imagen)
  12.    if (Imagen.type === "image/png" || Imagen.type === "image/jpeg") {
  13.      document.getElementById("imagen").src = URL.createObjectURL(event.target.files[0])
  14.    } else {
  15.      alert("De momento solo aceptamos imágenes PNG y JPG")
  16.    }
  17.  }
  18. </script>

Referencias:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file


Título: Re: [HTML][javascript] Dar vista previa de un input de tipo file o image...
Publicado por: .:Xx4NG3LxX:. en 20 Julio 2020, 17:45
Problema resuelto gracias @EdePC, y gracias a @XSStringManolo. Aunque su solución fue extensa, supongo que le habrá servido a alguien más.

Además, para eso estamos para compartir conocimiento con los demás.

Muchas gracias



Título: Re: [HTML][javascript] Dar vista previa de un input de tipo file o image...
Publicado por: @XSStringManolo en 21 Julio 2020, 07:52
También mencionar que hay un fallo gordo en Android con input type="file" donde no se puede guardar la instancia del navegador en memoria mientras se utiliza la aplicación nativa para seleccionar archivos.
Sospecho yo que el Garbaje Collector de Android llama al método onStop de Chrome (principalmente, afecta otros navegadores y apps con navegador integrado) por lo que se reinicia el navegador y se vuelve 100% imposible la subida de archivos.

Hay soluciones, son complejas.