diff --git a/QUICKSTART.md b/QUICKSTART.md index a49100d..705e9b1 100644 --- a/QUICKSTART.md +++ b/QUICKSTART.md @@ -69,9 +69,20 @@ $env:PATH += ";C:\poppler\Library\bin" **Port bereits belegt?** - Ändern Sie in app.py die Zeile: `app.run(debug=True, host='127.0.0.1', port=5001)` +**PDF-Vorschau funktioniert nicht?** +```powershell +# Poppler installieren (für PDF-Vorschauen) +scoop install poppler +# ODER manuell von GitHub herunterladen und PATH hinzufügen +``` + **Importfehler?** ```powershell # Virtuelle Umgebung erneut aktivieren .\venv\Scripts\Activate.ps1 pip install --upgrade -r requirements.txt -``` \ No newline at end of file +``` + +**Debug-Informationen:** +- Öffnen Sie http://127.0.0.1:5000/debug/check-dependencies +- Für PDF-spezifische Probleme: Browser-Konsole (F12) prüfen \ No newline at end of file diff --git a/app.py b/app.py index 93d81e6..457ff10 100644 --- a/app.py +++ b/app.py @@ -205,8 +205,14 @@ def upload_pdf(): page_count = len(pdf_reader.pages) # PDF Vorschau erstellen + print(f"Erstelle Vorschau für: {unique_filename}") preview_filename = create_pdf_preview(unique_filename) + if preview_filename: + print(f"Vorschau erfolgreich erstellt: {preview_filename}") + else: + print("Vorschau-Erstellung fehlgeschlagen, verwende Fallback") + return jsonify({ 'success': True, 'filename': unique_filename, @@ -214,7 +220,8 @@ def upload_pdf(): 'page_count': page_count, 'size': os.path.getsize(file_path), 'preview': preview_filename, - 'rotation': 0 # Standardrotation + 'rotation': 0, # Standardrotation + 'has_preview': preview_filename is not None }) return jsonify({'error': 'Nur PDF-Dateien sind erlaubt'}), 400 @@ -227,22 +234,110 @@ def create_pdf_preview(pdf_filename): try: pdf_path = os.path.join(UPLOAD_FOLDER, pdf_filename) - # PDF zu Bild konvertieren (nur erste Seite) - images = pdf2image.convert_from_path(pdf_path, first_page=1, last_page=1, dpi=150) + # Vorschau-Dateiname generieren + preview_filename = f"preview_{pdf_filename.rsplit('.', 1)[0]}.png" + preview_path = os.path.join(UPLOAD_FOLDER, preview_filename) - if images: - # Vorschau-Dateiname generieren - preview_filename = f"preview_{pdf_filename.rsplit('.', 1)[0]}.png" - preview_path = os.path.join(UPLOAD_FOLDER, preview_filename) + # PDF zu Bild konvertieren (nur erste Seite) + try: + # Versuche mit pdf2image (benötigt Poppler) + images = pdf2image.convert_from_path( + pdf_path, + first_page=1, + last_page=1, + dpi=150, + fmt='PNG' + ) - # Bild speichern - images[0].save(preview_path, 'PNG') - return preview_filename + if images: + # Bild speichern + images[0].save(preview_path, 'PNG') + print(f"PDF-Vorschau erstellt: {preview_filename}") + return preview_filename + + except ImportError: + print("pdf2image nicht verfügbar - PDF-Vorschau übersprungen") + return None + except Exception as pdf2image_error: + print(f"pdf2image Fehler: {str(pdf2image_error)}") + + # Fallback: Versuche mit PyPDF2 + reportlab eine einfache Vorschau zu erstellen + try: + return create_simple_pdf_preview(pdf_path, preview_path, pdf_filename) + except Exception as fallback_error: + print(f"Fallback Fehler: {str(fallback_error)}") + return None return None except Exception as e: - print(f"Fehler beim Erstellen der PDF-Vorschau: {str(e)}") + print(f"Allgemeiner Fehler beim Erstellen der PDF-Vorschau: {str(e)}") + return None + +def create_simple_pdf_preview(pdf_path, preview_path, pdf_filename): + """Erstellt eine einfache Text-basierte PDF-Vorschau als Fallback""" + try: + from PIL import Image, ImageDraw, ImageFont + + # Lese PDF-Informationen + with open(pdf_path, 'rb') as pdf_file: + pdf_reader = PyPDF2.PdfReader(pdf_file) + page_count = len(pdf_reader.pages) + + # Versuche Text der ersten Seite zu extrahieren + first_page_text = "" + if page_count > 0: + try: + first_page_text = pdf_reader.pages[0].extract_text()[:200] + except: + first_page_text = "PDF-Inhalt" + + # Erstelle ein einfaches Vorschaubild + img = Image.new('RGB', (300, 400), color='white') + draw = ImageDraw.Draw(img) + + # Versuche Standard-Font zu laden + try: + font = ImageFont.truetype("arial.ttf", 12) + title_font = ImageFont.truetype("arial.ttf", 16) + except: + font = ImageFont.load_default() + title_font = ImageFont.load_default() + + # Zeichne PDF-Vorschau + draw.rectangle([(10, 10), (290, 390)], outline='black', width=2) + draw.text((20, 20), f"PDF: {pdf_filename}", fill='black', font=title_font) + draw.text((20, 50), f"Seiten: {page_count}", fill='gray', font=font) + + # Text-Vorschau + if first_page_text: + # Text umbrechen + words = first_page_text.split() + lines = [] + current_line = "" + for word in words[:50]: # Maximal 50 Wörter + if len(current_line + word) < 35: + current_line += word + " " + else: + lines.append(current_line.strip()) + current_line = word + " " + if len(lines) >= 15: # Maximal 15 Zeilen + break + if current_line: + lines.append(current_line.strip()) + + y_pos = 80 + for line in lines: + draw.text((20, y_pos), line, fill='black', font=font) + y_pos += 18 + + # Speichere Vorschaubild + img.save(preview_path, 'PNG') + print(f"Fallback PDF-Vorschau erstellt: {preview_path}") + return os.path.basename(preview_path) + + except Exception as e: + print(f"Fehler bei Fallback-Vorschau: {str(e)}") return None @app.route('/api/pdf-to-images', methods=['POST']) @@ -366,13 +461,72 @@ def serve_uploaded_file(filename): file_path = os.path.join(UPLOAD_FOLDER, filename) if not os.path.exists(file_path): + print(f"Datei nicht gefunden: {file_path}") return "Datei nicht gefunden", 404 return send_file(file_path) except Exception as e: + print(f"Fehler beim Servieren der Datei {filename}: {str(e)}") return f"Fehler beim Laden der Datei: {str(e)}", 500 +@app.route('/debug/pdf-preview/') +def debug_pdf_preview(filename): + """Debug-Route für PDF-Vorschau-Probleme""" + try: + pdf_path = os.path.join(UPLOAD_FOLDER, filename) + + if not os.path.exists(pdf_path): + return jsonify({'error': f'PDF nicht gefunden: {pdf_path}'}) + + # Teste PDF-Vorschau-Erstellung + preview_filename = create_pdf_preview(filename) + + return jsonify({ + 'pdf_file': filename, + 'pdf_exists': os.path.exists(pdf_path), + 'preview_created': preview_filename is not None, + 'preview_filename': preview_filename, + 'preview_path': os.path.join(UPLOAD_FOLDER, preview_filename) if preview_filename else None, + 'preview_exists': os.path.exists(os.path.join(UPLOAD_FOLDER, preview_filename)) if preview_filename else False + }) + + except Exception as e: + return jsonify({'error': f'Debug-Fehler: {str(e)}'}) + +@app.route('/debug/check-dependencies') +def debug_check_dependencies(): + """Überprüft verfügbare Bibliotheken""" + deps = {} + + try: + import pdf2image + deps['pdf2image'] = 'verfügbar' + # Teste Poppler + try: + pdf2image.convert_from_bytes(b'dummy') + except Exception as e: + if 'poppler' in str(e).lower(): + deps['poppler'] = 'nicht gefunden' + else: + deps['poppler'] = 'möglicherweise verfügbar' + except ImportError: + deps['pdf2image'] = 'nicht installiert' + + try: + import PyPDF2 + deps['PyPDF2'] = 'verfügbar' + except ImportError: + deps['PyPDF2'] = 'nicht installiert' + + try: + from PIL import Image + deps['Pillow'] = 'verfügbar' + except ImportError: + deps['Pillow'] = 'nicht installiert' + + return jsonify(deps) + @app.route('/download/') def download_file(filename): """Download einer generierten Datei""" diff --git a/start.bat b/start.bat new file mode 100644 index 0000000..2bb53a6 --- /dev/null +++ b/start.bat @@ -0,0 +1,84 @@ +@echo off +echo =============================================== +echo PDF Editor Web App - Schnellstart +echo =============================================== +echo. + +:: Zum Projektverzeichnis wechseln +cd /d "%~dp0" + +:: Prüfen ob Python installiert ist +python --version >nul 2>&1 +if errorlevel 1 ( + echo [FEHLER] Python ist nicht installiert oder nicht im PATH! + echo Bitte installieren Sie Python 3.8+ von https://python.org + pause + exit /b 1 +) + +echo [INFO] Python gefunden: +python --version + +:: Prüfen ob virtuelle Umgebung existiert +if not exist "venv\" ( + echo [INFO] Erstelle virtuelle Umgebung... + python -m venv venv + if errorlevel 1 ( + echo [FEHLER] Konnte virtuelle Umgebung nicht erstellen! + pause + exit /b 1 + ) +) + +:: Virtuelle Umgebung aktivieren +echo [INFO] Aktiviere virtuelle Umgebung... +call venv\Scripts\activate.bat + +:: Abhängigkeiten installieren falls requirements.txt existiert +if exist "requirements.txt" ( + echo [INFO] Installiere/Update Abhängigkeiten... + pip install -r requirements.txt --quiet --disable-pip-version-check + if errorlevel 1 ( + echo [WARNUNG] Einige Abhängigkeiten konnten nicht installiert werden. + echo Versuchen Sie: pip install -r requirements.txt + ) +) + +:: Prüfen ob notwendige Ordner existieren +if not exist "uploads\" mkdir uploads +if not exist "output\" mkdir output + +:: Poppler-Check (für pdf2image) +echo [INFO] Prüfe Poppler-Installation... +python -c "import pdf2image; print('Poppler verfügbar')" 2>nul +if errorlevel 1 ( + echo [WARNUNG] Poppler nicht gefunden! PDF-zu-Bild-Konvertierung funktioniert möglicherweise nicht. + echo Installieren Sie Poppler: + echo - Windows: scoop install poppler ODER manuell von GitHub + echo - Details siehe README_INSTALL.md + echo. +) + +echo [INFO] Starte PDF Editor Web App... +echo [INFO] Die App wird unter http://127.0.0.1:5000 verfügbar sein +echo [INFO] Drücken Sie Ctrl+C zum Beenden +echo. + +:: Flask App starten +python app.py + +:: Falls Fehler beim Start +if errorlevel 1 ( + echo. + echo [FEHLER] Die Anwendung konnte nicht gestartet werden! + echo Mögliche Lösungen: + echo 1. Prüfen Sie ob Port 5000 frei ist + echo 2. Installieren Sie Abhängigkeiten: pip install -r requirements.txt + echo 3. Überprüfen Sie die Fehlermeldungen oben + echo. + pause +) + +echo. +echo Auf Wiedersehen! +pause \ No newline at end of file diff --git a/static/js/pdf-tools.js b/static/js/pdf-tools.js index 99b3807..1c7c7a1 100644 --- a/static/js/pdf-tools.js +++ b/static/js/pdf-tools.js @@ -15,6 +15,11 @@ document.addEventListener('DOMContentLoaded', function() { initializeDOMElements(); setupEventListeners(); setupDragAndDrop(); + + // Überprüfe Abhängigkeiten beim Laden + setTimeout(() => { + checkDependencies(); + }, 1000); }); function initializeDOMElements() { @@ -171,8 +176,9 @@ function createMergeFileItem(file, index) { // Create preview element const previewElement = file.preview ? `${file.original_name}` : - `
+ alt="${file.original_name}" onclick="showPdfModal('${file.preview}', '${file.original_name}', ${index})" + onerror="handlePreviewError(this, '${file.original_name}')">` : + `
`; @@ -500,6 +506,54 @@ function showError(message) { errorArea.scrollIntoView({ behavior: 'smooth', block: 'center' }); } +function handlePreviewError(img, originalName) { + // Ersetze fehlgeschlagenes Bild durch Fallback + const container = img.parentElement; + container.innerHTML = ` +
+ +
+ `; + + console.warn(`PDF-Vorschau konnte nicht geladen werden: ${originalName}`); + showNotification(`Vorschau für ${originalName} nicht verfügbar`, 'warning'); +} + +// Debug-Funktion für PDF-Vorschau-Probleme +async function debugPdfPreview(filename) { + try { + const response = await fetch(`/debug/pdf-preview/${filename}`); + const data = await response.json(); + console.log('PDF-Vorschau Debug:', data); + return data; + } catch (error) { + console.error('Debug-Fehler:', error); + return null; + } +} + +// Überprüfe Abhängigkeiten +async function checkDependencies() { + try { + const response = await fetch('/debug/check-dependencies'); + const data = await response.json(); + console.log('Abhängigkeiten:', data); + + // Warne bei fehlenden Abhängigkeiten + if (data.pdf2image !== 'verfügbar') { + showNotification('pdf2image nicht verfügbar - PDF-Vorschauen funktionieren möglicherweise nicht', 'warning'); + } + if (data.poppler === 'nicht gefunden') { + showNotification('Poppler nicht gefunden - Installieren Sie Poppler für PDF-Vorschauen', 'warning'); + } + + return data; + } catch (error) { + console.error('Abhängigkeits-Check fehlgeschlagen:', error); + return null; + } +} + // Global functions window.removeMergeFile = removeMergeFile; window.rotatePdf = rotatePdf; @@ -508,4 +562,7 @@ window.movePdfDown = movePdfDown; window.showPdfModal = showPdfModal; window.rotatePdfInModal = rotatePdfInModal; window.updatePdfPreviewSize = updatePdfPreviewSize; -window.showSplitPdfModal = showSplitPdfModal; \ No newline at end of file +window.showSplitPdfModal = showSplitPdfModal; +window.handlePreviewError = handlePreviewError; +window.debugPdfPreview = debugPdfPreview; +window.checkDependencies = checkDependencies; \ No newline at end of file