Cuando queremos mostrar una previa de una imagen desde JavaScript disponemos de una herramienta muy poderosa que todo FronEnd debe conocer: codificar el archivo binario a una ruta en formato Base64. En otras palabras, convertir una foto en un texto que puede ser incluido en cualquier elemento <img>
, o almacenado en una variable, guardado en una base de datos como texto, o enviado a un servicio externo como un API, etc. Sus posibilidades rozan el infinito.
Por ello he creado una sencilla función que se encarga de esta tarea. Además incorpora algunas características interesantes como:
- Ser usando de manera asíncrona o síncrona.
- Devolver una promesa que podemos gestionar en caso que la necesitemos en una ejecución asíncrona.
- Usar API nativo
FileReader
, sin extraños trucos.
DEMO
¿Quieres probarlo? Selecciona una imagen de tu equipo para ver la previa que será añadida a un elemento <img>
.
Para convertir el archivo en texto, que pueda ser interpretado por una etiqueta de imagen, deberemos transformarlo usando el API de FileReader
.
/**
* Returns a file in Base64URL format.
* @param {File} file
* @return {Promise<string>}
*/
async function encodeFileAsBase64URL(file) {
return new Promise((resolve) => {
const reader = new FileReader();
reader.addEventListener('loadend', () => {
resolve(reader.result);
});
reader.readAsDataURL(file);
});
};
Con tal solo darle un archivo a un input
de tipo file
ya obtendremos el string
. ¡Cuidado! Si no esperas con await
obtendrás una promesa, leer un archivo es una tarea asíncrona.
// Convierto la primera imagen del input en una ruta Base64
const base64URL = await encodeFileAsBase64URL(inputFile.files[0]);
// Anyado la ruta Base64 a la imagen
image.setAttribute('src', base64URL);
Todo unido quedaría de la siguiente forma.
<!doctype html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
</head>
<body>
<input type="file" id="input-foto">
<img src="" id="previa" width="400">
<script>
// Variables
const inputFile = document.querySelector('#input-foto');
const image = document.querySelector('#previa');
/**
* Returns a file in Base64URL format.
* @param {File} file
* @return {Promise<string>}
*/
async function encodeFileAsBase64URL(file) {
return new Promise((resolve) => {
const reader = new FileReader();
reader.addEventListener('loadend', () => {
resolve(reader.result);
});
reader.readAsDataURL(file);
});
};
// Eventos
inputFile.addEventListener('input', async (event) => {
// Convierto la primera imagen del input en una ruta Base64
const base64URL = await encodeFileAsBase64URL(inputFile.files[0]);
// Anyado la ruta Base64 a la imagen
image.setAttribute('src', base64URL);
});
</script>
</body>
</html>
Espero que os sea de utilidad.
{{ comments.length }} comentarios