DesanjuntarPDF es una aplicación de escritorio para Windows que detecta y extrae archivos adjuntos de documentos PDF. Reconoce tanto archivos embebidos como anotaciones de archivo y funciona completamente de forma local, sin Adobe Acrobat, cuentas ni servicios externos.
- Interfaz moderna con modos claro y oscuro, arrastrar y soltar y atajos de teclado.
- Icono propio integrado en la ventana, el ejecutable y formatos de favicon.
- Escaneo y extracción en segundo plano para mantener la ventana fluida.
- Cancelación segura tanto durante el análisis como durante la extracción.
- Compatibilidad con PDF protegidos mediante solicitud de contraseña.
- Detección de archivos embebidos y anotaciones de archivo.
- Búsqueda por nombre o extensión y filtro por origen del adjunto.
- Selección múltiple con recuento y tamaño total en tiempo real.
- Tres políticas para duplicados: renombrar, omitir o reemplazar.
- Escritura exclusiva o atómica para no dejar archivos parciales.
- Saneamiento de nombres peligrosos, rutas internas y nombres reservados de Windows.
- Informe JSON opcional con el resultado de cada extracción.
- Preferencias persistentes para tema, destino y opciones habituales.
- Procesamiento local: los documentos nunca se suben a internet.
git clone https://github.com/IAZARA/DesanjuntarPDF.git
cd DesanjuntarPDF
python -m venv venv
.\venv\Scripts\activate
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
python src\main.pyTambién puedes abrir un PDF directamente desde la línea de comandos:
python src\main.py "C:\Documentos\informe.pdf"- Arrastra un PDF a la ventana o pulsa Seleccionar un PDF.
- Si el documento está protegido, ingresa su contraseña.
- Busca, filtra y marca los adjuntos que quieras recuperar.
- Elige la carpeta de destino y la política para nombres duplicados.
- Pulsa Extraer archivos.
La aplicación propone por defecto una carpeta DesanjuntarPDF dentro de
Descargas. Puedes cambiarla antes de cada extracción y abrirla desde la propia
interfaz.
| Opción | Comportamiento |
|---|---|
| Conservar ambos | Agrega un sufijo numérico, por ejemplo informe_1.xlsx. |
| Omitir el nuevo | Conserva el archivo existente y registra el adjunto como omitido. |
| Reemplazar | Escribe primero un temporal y reemplaza el destino de forma atómica. |
| Atajo | Acción |
|---|---|
Ctrl+O |
Seleccionar un PDF. |
Ctrl+F |
Enfocar la búsqueda. |
Ctrl+Shift+A |
Seleccionar todos los adjuntos visibles. |
Ctrl+Shift+D |
Deseleccionar los adjuntos visibles. |
Ctrl+Enter |
Iniciar la extracción. |
Esc |
Cancelar la operación activa. |
En Windows:
python -m pip install -r requirements.txt -r requirements-build.txt
python build.pyTambién puedes ejecutar build_windows.bat. El resultado queda en:
dist\DesanjuntarPDF.exe
Consulta la guía de compilación para Windows para ver requisitos y solución de problemas.
python -m pip install -r requirements.txt -r requirements-build.txt -r requirements-dev.txt
python -m ruff check .
python -m compileall src build.py create_icon.py
python -m pytest
python -m pip_audit -r requirements.txtLas capturas del README se pueden regenerar con:
python scripts\generate_demo_assets.pyEl script crea un PDF temporal con adjuntos, renderiza ambos estados reales de la aplicación y elimina el documento de prueba al finalizar.
DesanjuntarPDF valida la firma del PDF antes de procesarlo, nunca interpreta el nombre de un adjunto como ruta, limita cada archivo extraído a 2 GB y evita sobrescrituras accidentales. Las contraseñas se conservan únicamente en memoria mientras el documento está abierto.
Consulta SECURITY.md para reportar una vulnerabilidad.
DesanjuntarPDF/
├── assets/ # Banner, icono maestro y favicon
├── docs/images/ # Capturas reales de la aplicación
├── scripts/ # Generación reproducible de demos
├── src/main.py # Interfaz PyQt6 y tareas en segundo plano
├── src/pdf_service.py # Validación, escaneo y extracción segura
├── src/theme.py # Temas claro y oscuro
├── tests/ # Pruebas de seguridad y procesamiento PDF
├── build.py # Build portable con PyInstaller
└── requirements*.txt # Dependencias separadas por finalidad
Distribuido bajo licencia MIT. Consulta LICENSE.


