Blob y File API: Manejo de Archivos Binarios en JavaScript
Aprende a trabajar con archivos binarios usando Blob y File API para leer, crear y manipular datos de archivos directamente en el navegador.
TL;DR - Resumen rápido
- Blob representa datos inmutables de tipo raw binary large object
- File hereda de Blob y añade metadatos como nombre y fecha de modificación
- Puedes crear Blobs desde texto, arrays, otros Blobs o mezclas de todo
- URL.createObjectURL() genera URLs temporales para descargar Blobs
- FileReader permite leer el contenido de archivos en diferentes formatos
Introducción a Blob y File API
Cuando trabajas con aplicaciones web, eventualmente necesitarás manejar archivos: imágenes, PDFs, documentos de texto, videos y más. Tradicionalmente, esto requería enviar archivos al servidor para procesarlos, pero con Blob y File API puedes manipular archivos directamente en el navegador sin necesidad de backend.
Blob (Binary Large Object) es un objeto que representa datos inmutables de tipo raw binary. Es la base para manejar cualquier tipo de archivo en JavaScript moderno. File API extiende Blob añadiendo metadatos específicos de archivos como nombre, tipo MIME y fecha de modificación.
- Manipular imágenes sin servidor (redimensionar, recortar, convertir formatos)
- Crear y descargar archivos dinámicamente (CSV, JSON, PDF)
- Previsualizar archivos antes de subirlos
- Procesar archivos grandes en chunks para mejor rendimiento
- Implementar funcionalidades de drag & drop de archivos
Soporte del navegador
Blob y File API tienen soporte universal en todos los navegadores modernos. No necesitas polyfills ni librerías externas para usar estas capacidades.
¿Qué es un Blob?
Un Blob es un objeto inmutable que representa datos binarios crudos. "Inmutable" significa que una vez creado, no puedes modificar su contenido. Si necesitas cambiar los datos, debes crear un nuevo Blob. Los Blobs pueden almacenar cualquier tipo de datos: texto, imágenes, audio, video o datos binarios arbitrarios.
Crear un Blob
El constructor de Blob acepta un array de datos y un objeto de opciones. Los datos pueden ser strings, arrays de bytes, otros Blobs o una mezcla de todos. El objeto options permite especificar el tipo MIME del contenido.
El primer ejemplo crea un Blob simple de texto plano, mientras que el segundo muestra cómo crear un Blob desde datos binarios (un array de bytes). El tipo MIME es importante porque indica al navegador cómo interpretar los datos. Por ejemplo, "text/plain" para texto, "application/json" para JSON, "image/jpeg" para imágenes JPEG.
Tipos MIME comunes
text/plain - Texto planoapplication/json - JSONimage/jpeg - Imagen JPEGimage/png - Imagen PNGapplication/pdf - Documento PDFtext/csv - Archivo CSV
Propiedades del Blob
Los objetos Blob tienen dos propiedades principales: size y type. Size devuelve el tamaño en bytes del contenido, mientras que type devuelve el tipo MIME especificado al crear el Blob.
Estas propiedades son útiles para validar archivos antes de procesarlos. Por ejemplo, puedes verificar que un archivo no exceda cierto tamaño o que tenga el tipo MIME esperado antes de subirlo o procesarlo.
Métodos de Blob
Los Blobs proporcionan varios métodos útiles para leer y manipular su contenido. Los más importantes son slice() para dividir Blobs, text() y arrayBuffer() para leer el contenido, y stream() para procesar datos de forma continua.
El método slice() es especialmente útil para procesar archivos grandes en chunks sin cargar todo el archivo en memoria. Los métodos text() y arrayBuffer() devuelven Promesas que resuelven con el contenido del Blob en el formato especificado.
- slice(start, end) - Extrae una porción del Blob sin modificar el original
- text() - Lee el contenido como string (devuelve una Promise)
- arrayBuffer() - Lee el contenido como ArrayBuffer para datos binarios
- stream() - Convierte el Blob en un ReadableStream para procesamiento continuo
File API
File API extiende Blob añadiendo metadatos específicos de archivos. Cuando un usuario selecciona un archivo mediante un input type="file" o mediante drag & drop, el navegador crea objetos File que incluyen información como el nombre del archivo, la fecha de última modificación y el tamaño.
Diferencias entre Blob y File
File hereda todas las propiedades y métodos de Blob, pero añade propiedades adicionales que representan metadatos del sistema de archivos. Esto hace que File sea más adecuado cuando trabajas con archivos reales del sistema, mientras que Blob es más flexible para datos generados programáticamente.
Este ejemplo muestra cómo acceder a un archivo seleccionado por el usuario. El evento change del input file proporciona acceso a la propiedad files, que es una FileList. Cada elemento de esta lista es un objeto File con propiedades como name, lastModified y type.
Usos Prácticos de Blob y File API
La combinación de Blob y File API permite implementar funcionalidades potentes directamente en el navegador. Veamos dos de los usos más comunes: descargar archivos generados dinámicamente y previsualizar archivos antes de subirlos.
Descargar un Blob
Para descargar un Blob, necesitas crear una URL temporal usando URL.createObjectURL(). Este método genera una URL única que apunta al Blob en memoria. Después de usar la URL, es importante liberarla con URL.revokeObjectURL() para evitar memory leaks.
Este patrón es muy útil para generar archivos dinámicamente sin servidor. Por ejemplo, puedes exportar datos de una tabla a CSV, generar un reporte en PDF, o crear una imagen procesada en canvas y permitir al usuario descargarla. El enlace temporal se crea programáticamente, se simula un clic, y luego se elimina.
Memory leak con object URLs
Cada llamada a URL.createObjectURL() crea una referencia en memoria. Si no llamas a URL.revokeObjectURL() después de usar la URL, los Blobs permanecerán en memoria indefinidamente, causando memory leaks especialmente en aplicaciones SPA.
Subir un Blob al servidor
Los Blobs se pueden enviar directamente al servidor usando FormData o como cuerpo de una petición fetch. FormData es la forma más común porque permite enviar archivos junto con otros datos del formulario.
Este ejemplo muestra dos formas de subir un Blob: usando FormData y enviando el Blob directamente como cuerpo de la petición. FormData es más flexible porque permite enviar múltiples archivos y datos adicionales, mientras que enviar el Blob directamente es más simple cuando solo necesitas enviar un archivo.
Procesar Archivos Grandes en Chunks
Cuando trabajas con archivos grandes, es mejor procesarlos en chunks (fragmentos) usando el método slice(). Esto evita cargar todo el archivo en memoria de una vez y permite implementar subidas resumibles y barras de progreso. Esta técnica es esencial para aplicaciones que manejan archivos de varios megabytes o gigabytes.
Este patrón es fundamental para subir archivos grandes de forma eficiente. Puedes enviar cada chunk al servidor independientemente, mostrar progreso al usuario, y reintentar solo los chunks que fallen. Servicios como Google Drive y Dropbox usan esta técnica para subidas confiables.
Tamaño óptimo de chunks
Un tamaño de chunk entre 100KB y 1MB es generalmente óptimo. Chunks muy pequeños generan demasiadas peticiones HTTP, mientras que chunks muy grandes no permiten mostrar progreso granular y dificultan reintentos en caso de error.
Errores Comunes
Al trabajar con Blob y File API, hay varios errores comunes que puedes encontrar. Conocerlos de antemano te ayudará a evitar problemas y a depurar más rápido cuando ocurran.
El primer error es olvidar revocar las object URLs, causando memory leaks en aplicaciones que generan muchas descargas. El segundo muestra que los Blobs son inmutables: no puedes modificar su contenido una vez creados. El tercero enfatiza la importancia de especificar siempre el tipo MIME correcto para evitar problemas de interpretación.
Resumen: Blob y File API
Conceptos principales:
- •Blob representa datos binarios inmutables en el navegador
- •File extiende Blob añadiendo metadatos como nombre y fecha
- •URL.createObjectURL() genera URLs temporales para acceder a Blobs
- •slice() permite dividir Blobs para procesar archivos grandes en chunks
- •text() y arrayBuffer() leen el contenido del Blob de forma asíncrona
Mejores prácticas:
- •Siempre revoca object URLs con URL.revokeObjectURL() para evitar memory leaks
- •Valida tipo MIME y tamaño antes de procesar archivos del usuario
- •Usa slice() con chunks de 100KB-1MB para archivos grandes
- •Especifica siempre el tipo MIME correcto al crear Blobs
- •Usa FormData para subir archivos con datos adicionales del formulario