downloadFile
Paquete: @tiendana/utils
Descarga un archivo desde una URL programáticamente, creando un enlace temporal que simula un click del usuario. Útil para descargas automáticas o botones de descarga personalizados.
Características
✅ Descarga desde cualquier URL
✅ Nombre de archivo personalizable
✅ Abre en nueva pestaña (target="_blank")
✅ Nombre automático desde URL si no se especifica
✅ Limpia el DOM después de la descarga
✅ Compatible con Blob URLs y URLs remotas
Firma
function downloadFile(url: string, filename?: string | null): void
Parámetros
| Parámetro | Tipo | Descripción | Requerido |
|---|---|---|---|
url | string | URL del archivo a descargar | ✅ |
filename | string | null | undefined | Nombre del archivo descargado (con extensión) | ❌ |
Retorno
Tipo: void
No retorna nada. Inicia la descarga automáticamente.
Ejemplos de Uso
Descarga Básica
import { downloadFile } from '@tiendana/utils';
downloadFile('https://example.com/document.pdf');
// Descarga como "document.pdf"
Con Nombre Personalizado
downloadFile(
'https://example.com/file123.pdf',
'Mi_Documento_2024.pdf'
);
// Descarga como "Mi_Documento_2024.pdf"
Descargar Blob
function downloadBlob() {
const blob = new Blob(['Hola Mundo'], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
downloadFile(url, 'mensaje.txt');
// Cleanup después de un delay
setTimeout(() => URL.revokeObjectURL(url), 100);
}
Botón de Descarga
function DownloadButton({ fileUrl, fileName }: { fileUrl: string; fileName: string }) {
const handleDownload = () => {
downloadFile(fileUrl, fileName);
};
return (
<button onClick={handleDownload}>
⬇️ Descargar {fileName}
</button>
);
}
Descargar CSV Generado
function exportToCSV(data: any[]) {
const csvContent = data.map(row =>
Object.values(row).join(',')
).join('\n');
const blob = new Blob([csvContent], { type: 'text/csv' });
const url = URL.createObjectURL(blob);
downloadFile(url, 'data.csv');
setTimeout(() => URL.revokeObjectURL(url), 100);
}
Descargar JSON
function downloadJSON(data: any, filename: string) {
const json = JSON.stringify(data, null, 2);
const blob = new Blob([json], { type: 'application/json' });
const url = URL.createObjectURL(blob);
downloadFile(url, filename);
setTimeout(() => URL.revokeObjectURL(url), 100);
}
// Uso
downloadJSON({ name: 'Juan', age: 30 }, 'user.json');
Descargar Imagen
function DownloadImageButton({ imageUrl }: { imageUrl: string }) {
const handleDownload = () => {
downloadFile(imageUrl, 'imagen.jpg');
};
return <button onClick={handleDownload}>💾 Guardar imagen</button>;
}
Descargar Desde Canvas
function downloadCanvasAsImage(canvas: HTMLCanvasElement) {
canvas.toBlob((blob) => {
if (blob) {
const url = URL.createObjectURL(blob);
downloadFile(url, 'canvas-image.png');
setTimeout(() => URL.revokeObjectURL(url), 100);
}
});
}
Descargar Reporte
interface Report {
title: string;
content: string;
date: Date;
}
function DownloadReportButton({ report }: { report: Report }) {
const handleDownload = () => {
const content = `
Reporte: ${report.title}
Fecha: ${report.date.toLocaleDateString()}
${report.content}
`;
const blob = new Blob([content], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const filename = `${report.title.replace(/\s+/g, '_')}.txt`;
downloadFile(url, filename);
setTimeout(() => URL.revokeObjectURL(url), 100);
};
return <button onClick={handleDownload}>📥 Descargar reporte</button>;
}
Descargar Excel (Blob)
async function downloadExcel() {
const response = await fetch('https://api.example.com/export/excel');
const blob = await response.blob();
const url = URL.createObjectURL(blob);
downloadFile(url, 'reporte.xlsx');
setTimeout(() => URL.revokeObjectURL(url), 100);
}
Descargar ZIP
async function downloadZipFile(fileId: string) {
const response = await fetch(`/api/files/${fileId}/download`);
const blob = await response.blob();
const url = URL.createObjectURL(blob);
downloadFile(url, `archive_${fileId}.zip`);
setTimeout(() => URL.revokeObjectURL(url), 100);
}
Casos de Uso Comunes
- Descargar archivos: PDFs, imágenes, documentos
- Exportar datos: CSV, JSON, Excel
- Guardar reportes: Reportes generados dinámicamente
- Descargar imágenes: Desde canvas, URLs remotas
- Backup de datos: Exportar configuraciones, backups
- Descargar archivos generados: Facturas, tickets, certificados
- Guardar recursos: Videos, audio, archivos multimedia
Nombre de Archivo
Nombre Automático
Si no se proporciona filename, se extrae el nombre del último segmento de la URL:
downloadFile('https://example.com/docs/report.pdf');
// Descarga como "report.pdf"
downloadFile('https://example.com/files/123/download');
// Descarga como "download"
URL sin Último Segmento
El nombre se calcula con url.split('/').pop() ?? 'file'. El valor 'file' solo se usa si pop() devuelve undefined, algo que no ocurre con una URL normal. Si la URL termina en /, el segmento es un string vacío y el atributo download queda vacío, así que el navegador decide el nombre:
downloadFile('https://example.com/');
// download="" → el navegador elige el nombre
Nombre Personalizado
Es recomendable siempre proporcionar un nombre personalizado para mejor UX:
downloadFile(url, 'Mi_Reporte_2024.pdf');
// ✅ Mejor experiencia de usuario
Funcionamiento Interno
La función:
- Crea un elemento
<a>temporal - Establece
target="_blank"para abrir en nueva pestaña - Establece
hrefcon la URL del archivo - Establece atributo
downloadcon el nombre del archivo - Añade el elemento al DOM
- Simula un click en el elemento
- Remueve el elemento del DOM
const link = document.createElement('a');
link.setAttribute('target', '_blank');
link.setAttribute('href', url);
link.setAttribute('download', filename);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
Notas Técnicas
- CORS: Para URLs remotas, el servidor debe permitir CORS
- Blob URLs: Debe llamar a
URL.revokeObjectURL()después de la descarga - Same-origin: Funciona mejor con archivos del mismo dominio
- Navegador: El navegador puede mostrar un diálogo de descarga
- Extensión: Asegúrate de incluir la extensión en el filename
- DOM cleanup: La función limpia automáticamente el elemento
<a>creado
Limitaciones
Para descargar archivos de dominios externos, el servidor debe tener CORS habilitado:
// ❌ Puede fallar si el servidor no tiene CORS
downloadFile('https://external-site.com/file.pdf');
// ✅ Funciona con mismo dominio
downloadFile('/files/document.pdf');
// ✅ Funciona con Blob URLs
const blob = new Blob([data]);
const url = URL.createObjectURL(blob);
downloadFile(url, 'file.pdf');
Para archivos externos sin CORS, considera usar un proxy en tu servidor.
Cuando usas URL.createObjectURL(), debes liberar la memoria manualmente:
const url = URL.createObjectURL(blob);
downloadFile(url, 'file.pdf');
// ⚠️ IMPORTANTE: Liberar memoria después de la descarga
setTimeout(() => {
URL.revokeObjectURL(url);
}, 100);
El timeout es necesario para dar tiempo a que la descarga inicie.
Algunos navegadores pueden bloquear descargas que no son iniciadas directamente por un click del usuario. Asegúrate de llamar a downloadFile() dentro de un event handler de click:
// ✅ Funciona - iniciado por click
<button onClick={() => downloadFile(url)}>Descargar</button>
// ❌ Puede ser bloqueado
useEffect(() => {
downloadFile(url); // No iniciado por usuario
}, []);
Browser Support
| Navegador | Versión | Notas |
|---|---|---|
| Chrome | Todos | Soporte completo |
| Firefox | Todos | Soporte completo |
| Safari | 10.1+ | Atributo download soportado |
| Edge | Todos | Soporte completo |
| Opera | Todos | Soporte completo |
Safari < 10.1
En versiones antiguas de Safari, el atributo download no funciona. El archivo se abrirá en lugar de descargarse.
Ver También
- copyTextToClipboard - Copiar texto al portapapeles
- Cookies - Trabajar con cookies del navegador