- Python 3.11+ (recomendado 3.11 o 3.12)
- Redis
- Servidor SFTP
python3 -m venv .venv
source .venv/bin/activate # Linux/Mac
# .venv\Scripts\activate # Windowspip install --upgrade pip
pip install -r requirements.txtNota: Si tienes Python 3.14+, usa Python 3.11 o 3.12 ya que pydantic-core no tiene binarios precompilados para Python 3.14.
Edita el archivo .env:
SFTP_HOST=tu_servidor_sftp
SFTP_PORT=22
SFTP_USERNAME=tu_usuario
SFTP_PASSWORD=tu_password
SFTP_ROOT_PATH=/ruta/remota
CELERY_BROKER_URL=redis://localhost:6379/0
CELERY_RESULT_BACKEND=redis://localhost:6379/0
WEBSOCKET_HOST=0.0.0.0
WEBSOCKET_PORT=8000
LOG_LEVEL=INFO# Instalar redis si no lo tienes
# Ubuntu/Debian: sudo apt install redis-server
# Mac: brew install redis
redis-servercelery -A src.infrastructure.celery worker --loglevel=infopython main.pypython3 -m http.server 8080O si prefieres usar gunicorn:
pip install gunicorn
gunicorn main:app --workers 4 --bind 0.0.0.0:8000| Método | Endpoint | Descripción |
|---|---|---|
| POST | /api/v1/sftp/upload |
Subir archivo |
| POST | /api/v1/sftp/download |
Descargar archivo |
| POST | /api/v1/sftp/delete |
Eliminar archivo/directorio |
| GET | /api/v1/sftp/list/{path} |
Listar directorio |
| GET | /api/v1/sftp/info/{path} |
Obtener metadata |
| POST | /api/v1/sftp/mkdir |
Crear directorio |
| POST | /api/v1/sftp/rename |
Renombrar |
| POST | /api/v1/sftp/copy |
Copiar archivo |
| POST | /api/v1/sftp/hash |
Obtener hash de archivo |
| GET | /api/v1/sftp/disk-usage/{path} |
Uso de disco |
| GET | /api/v1/sftp/test-connection |
Probar conexión |
| GET | /api/v1/sftp/task/{task_id} |
Estado de tarea |
| GET | /api/v1/sftp/audit-logs |
Logs de auditoría |
| GET | /api/v1/sftp/health |
Health check |
| WS | /api/v1/sftp/ws/{client_id}?task_id= |
WebSocket para progreso |
curl -X GET http://localhost:8000/api/v1/sftp/test-connectioncurl -X GET "http://localhost:8000/api/v1/sftp/list/"curl -X GET "http://localhost:8000/api/v1/sftp/info/archivo.txt"curl -X POST http://localhost:8000/api/v1/sftp/upload \
-F file=@/home/nian/Documents/desarrollo/softron/proyectos/dataexpress/docs/reconocimiento_gestion_documental/SR2052628_CATALOGO_PARTICULARADMIN_SIGLA_20251106095645.csv \
-F client_id=sftpcurl -X POST "http://localhost:8000/api/v1/sftp/delete" \
-H "Content-Type: application/json" \
-d '{"remote_path": "/archivo.txt"}'curl -X POST "http://localhost:8000/api/v1/sftp/rename" \
-H "Content-Type: application/json" \
-d '{"old_path": "/viejo.txt", "new_path": "/nuevo.txt"}'curl -X POST "http://localhost:8000/api/v1/sftp/copy" \
-H "Content-Type: application/json" \
-d '{"source_path": "/origen.txt", "dest_path": "/destino.txt"}'curl -X POST "http://localhost:8000/api/v1/sftp/hash" \
-H "Content-Type: application/json" \
-d '{"remote_path": "/archivo.txt", "algorithm": "sha256"}'curl -X GET "http://localhost:8000/api/v1/sftp/audit-logs?limit=10"Conecta al WebSocket para recibir actualizaciones en tiempo real:
ws://localhost:8000/api/v1/sftp/ws/{client_id}?task_id={task_id}
Mensaje de ejemplo recibido:
{
"task_id": "abc-123",
"operation": "upload",
"progress": 50.0,
"status": "in_progress",
"message": "Uploading...",
"bytes_transferred": 524288,
"total_bytes": 1048576,
"timestamp": "2024-01-01T00:00:00"
}src/
├── domain/ # Capa de dominio (reglas de negocio)
│ ├── entities/ # Entidades del negocio
│ ├── repositories/ # Interfaces (puertos)
│ └── services/ # Servicios de dominio
├── application/ # Casos de uso
│ ├── dtos/ # Data Transfer Objects
│ └── use_cases/ # Implementación de casos de uso
├── infrastructure/ # Implementaciones externas
│ ├── sftp/ # Cliente SFTP
│ ├── database/ # Repositorio de auditoria
│ ├── websocket/ # Manejador WebSocket
│ └── celery/ # Configuración Celery
├── presentation/ # Capa de presentación
│ └── api/
│ ├── routers/ # Endpoints FastAPI
│ └── dependencies/ # Inyección de dependencias
└── shared/ # Utilidades compartidas
├── config/ # Configuración
└── exceptions/ # Excepciones personalizadas
{
"success": true,
"status": "success",
"message": "Operation completed successfully",
"metadata": {
"name": "file.txt",
"path": "/remote/path/file.txt",
"size": 1024,
"permissions": "0o100644",
"modified_time": "2024-01-01T00:00:00",
"is_directory": false,
"is_link": false
},
"operation": "upload",
"timestamp": "2024-01-01T00:00:00",
"duration_seconds": 1.5,
"additional_data": {}
}{
"success": false,
"status": "failed",
"message": "File not found",
"error_code": "NOT_FOUND",
"operation": "download",
"timestamp": "2024-01-01T00:00:00",
"duration_seconds": 0.5,
"additional_data": {}
}#!/bin/bash
echo "Starting Redis..."
redis-server --daemonize yes
echo "Starting Celery Worker..."
celery -A src.infrastructure.celery worker --loglevel=info &
echo "Starting FastAPI Server..."
python main.pyversion: '3.8'
services:
redis:
image: redis:7-alpine
ports:
- "6379:6379"
api:
build: .
ports:
- "8000:8000"
environment:
- SFTP_HOST=${SFTP_HOST}
- SFTP_PORT=${SFTP_PORT}
- SFTP_USERNAME=${SFTP_USERNAME}
- SFTP_PASSWORD=${SFTP_PASSWORD}
- CELERY_BROKER_URL=redis://redis:6379/0
- CELERY_RESULT_BACKEND=redis://redis:6379/0
depends_on:
- redis
celery:
build: .
command: celery -A src.infrastructure.celery worker --loglevel=info
environment:
- SFTP_HOST=${SFTP_HOST}
- CELERY_BROKER_URL=redis://redis:6379/0
- CELERY_RESULT_BACKEND=redis://redis:6379/0
depends_on:
- redis- La API usa Clean Architecture con inyección de dependencias
- Todas las operaciones generan logs de auditoría
- WebSocket permite seguimiento en tiempo real de uploads/downloads
- Las tareas largas (upload/download) se procesan via Celery