Descripción general
Este artículo explica cómo desarrollar un prototipo funcional de una herramienta de descarga que permite a los usuarios descargar archivos a partir de URLs proporcionadas. El prototipo incluye visualización del progreso y notificaciones al finalizar la descarga, utilizando OpenSpeedy como base y un stack tecnológico ligero.
Requisitos y seleccción de tecnologías
La necesidad principal es implementar una interfaz donde se ingrese una URL y se inicie la descarga con seguimiento en tiempo real. Para un desarrollo ágil, se optó por:
- Frontend: HTML y JavaScript para la interfaz de usuario y manejo de eventos.
- Backend: Python con Flask para gestionar las solicitudes de descarga y exponer una API REST.
Diseño de la interfaz de usuario
El frontend se compone de un campo de entrada para la URL, un botón de acción y una barra de progreso para mostrar el avance. A continuación, un ejemplo de código HTML simplificado:
<input type="text" id="enlaceArchivo" placeholder="Escribe la URL del recurso">
<button onclick="solicitarDescarga()">Iniciar descarga</button>
<div id="indicadorProgreso"></div>
El script JavaScript maneja las peticiones al backend y actualiza dinámicamente el indicador de progreso basado en las respuestas del servidor.
Implementación del servidor backend
El backend con Flask define endpoints para iniciar descargas y consultar el progreso. Se utiliza el enfoque de descarga por bloques para calcular el avance con precisión. Ejemplo de código en Python:
from flask import Flask, request, jsonify
import requests
import threading
import uuid
aplicacion = Flask(__name__)
almacen_descargas = {}
def descargar_archivo(identificador, url):
respuesta = requests.get(url, stream=True)
total_bytes = int(respuesta.headers.get('content-length', 0))
bytes_descargados = 0
for bloque in respuesta.iter_content(chunk_size=1024):
bytes_descargados += len(bloque)
almacen_descargas[identificador]['avance'] = (bytes_descargados / total_bytes) * 100 if total_bytes > 0 else 0
@aplicacion.route('/iniciar', methods=['POST'])
def iniciar_descarga():
datos = request.json
url_recurso = datos.get('url')
id_sesion = str(uuid.uuid4())
almacen_descargas[id_sesion] = {'avance': 0}
hilo = threading.Thread(target=descargar_archivo, args=(id_sesion, url_recurso))
hilo.start()
return jsonify({'identificador': id_sesion})
@aplicacion.route('/avance/<identificador>')
def obtener_avance(identificador):
if identificador in almacen_descargas:
return jsonify({'porcentaje': almacen_descargas[identificador]['avance']})
return jsonify({'error': 'Sesión no válida'}), 404
Integración y solución de problemas
Al unir frontend y backend, se resolvieron desafíos como las restricciones CORS mediante la extensión Flask-CORS, y se implementó un mecanismo de sondeo en el frontend para sincrnoizar el progreso sin sobrecargar el sistema. También se añadió manejo de errores para conexiones fallidas o URLs inválidas.
Mejoras de rendimiento
Para optimizar el prototipo, se aplicaron técnicas básicas como:
- Caché de descargas para evitar solicitudes repetidas del mismo recurso.
- Reutilización de conexiones HTTP mediante sesiones persistentes.
- Procesamiento en flujo para archivos grandes, reduciendo el uso de memoria.
Este enfoque permite tener un prototipo funcional con menos de 200 líneas de código, ideal para validaciones rápidas o necesidades puntuales.