# Batch Image Uploader

Ein Python-Skript für automatischen Batch-Upload von Bildern mit Metadaten-Extraktion.

## Features

- 🔍 **Rekursives Verzeichnis-Scanning** nach unterstützten Bildformaten
- 📊 **Automatische Metadaten-Extraktion** aus EXIF-Daten und Pfad-Struktur  
- 🚀 **Batch-Upload** mit konfigurierbarer Chunk-Größe
- 📈 **Progress-Tracking** und Error-Handling
- 🏗️ **Strukturierte Metadaten** (Jahr, Titel, Beschreibung, Name)

## Installation

```bash
# Python Dependencies installieren
pip install -r requirements.txt

# Oder einzeln:
pip install requests pillow
```

## Usage

### Einfacher Upload
```bash
# Linux/macOS
python batch_uploader.py /path/to/images --titel "Meine Foto-Sammlung"

# Windows
python batch_uploader.py "C:\Users\username\Photos" --titel "Meine Foto-Sammlung"
```

### Erweiterte Optionen
```bash
# Linux/macOS - Mit Standard-Name und Backend-URL
python batch_uploader.py ./photos \
  --titel "Urlaubsbilder 2024" \
  --name "Max Mustermann" \
  --backend http://localhost:5000 \
  --chunk-size 10

## Windows / WSL: Pfade mit Leerzeichen und Sonderzeichen

Windows-PowerShell (empfohlen):
```powershell
# Doppelte Anführungszeichen um den kompletten Pfad, Backslashes bleiben unverändert
python batch_uploader.py "C:\Users\lotzm\Nextcloud2\HH DropFolder with quota\=NutzerBildUploads=" --titel "Nextcloud Archive" --name "Lotz M." --verbose
```

Windows (CMD) – ohne Anführungszeichen mit Escapes oder mit Anführungszeichen:
```bat
REM Mit Backslashes escapen (CMD):
python batch_uploader.py C:\Users\lotzm\Nextcloud2\HH\ DropFolder\ with\ quota\=NutzerBildUploads= --titel "Nextcloud Archive"

REM Oder einfacher mit Anführungszeichen:
python batch_uploader.py "C:\Users\lotzm\Nextcloud2\HH DropFolder with quota\=NutzerBildUploads=" --titel "Nextcloud Archive"
```

WSL / Linux (bash) – Pfad in /mnt/c/... verwenden, ohne zusätzliche Backslashes in Quotes:
```bash
python3 batch_uploader.py "/mnt/c/Users/lotzm/Nextcloud2/HH DropFolder with quota/=NutzerBildUploads=" --titel "Nextcloud Archive" --name "Lotz M." --verbose
# oder ohne Quotes, mit Backslash-Escapes:
python3 batch_uploader.py /mnt/c/Users/lotzm/Nextcloud2/HH\ DropFolder\ with\ quota/=NutzerBildUploads= --titel "Nextcloud Archive"
```

Hinweis:
- Verwende nicht gleichzeitig single-quotes und Backslash-Escapes: in single-quotes werden Backslashes nicht als Escape interpretiert.
- Prüfe mit `ls` (oder Tab-Completion), ob der Pfad exakt existiert, bevor du das Skript startest.

# Dry-Run (nur Analyse) - Cross-Platform
python batch_uploader.py /photos --dry-run --verbose
python batch_uploader.py "D:\Photos" --dry-run --verbose

# Nicht-rekursiv (nur Top-Level)
python batch_uploader.py ./images --no-recursive
```

### Parameter

| Parameter | Beschreibung | Standard |
|-----------|--------------|----------|
| `directory` | Verzeichnis mit Bildern (Required) | - |
| `--titel` | Standard-Titel für alle Bilder | Aus Pfad extrahiert |
| `--name` | Standard-Name für alle Bilder | Leer |
| `--backend` | Backend-URL | `http://localhost:5000` |
| `--chunk-size` | ~~Bilder pro Upload-Batch~~ (Deprecated) | ~~5~~ |
| `--no-recursive` | Nicht in Unterverzeichnisse | `False` |
| `--dry-run` | Nur Analyse, kein Upload | `False` |
| `--verbose` | Detailliertes Logging | `False` |

## Metadaten-Extraktion

### Erwartete Struktur: `Photos/Jahr/Name/Projekt/dateiname.endung`

### Jahr
1. **Verzeichnis-Struktur**: Aus dem Jahr-Verzeichnis (z.B. `2024/`)
2. **EXIF-Daten**: `DateTime`, `DateTimeOriginal`, `DateTimeDigitized` 
3. **Pfad-Pattern**: `2024`, `2023`, etc. in anderen Verzeichnis/Dateinamen
4. **Fallback**: Aktuelles Jahr

### Titel
1. **Parameter**: `--titel` (überschreibt alles)
2. **Projekt-Verzeichnis**: `Urlaub_Mallorca` → `Urlaub Mallorca`
3. **Cleaning**: Unterstriche/Bindestriche → Leerzeichen

### Beschreibung
1. **README.md im Projekt-Verzeichnis**: Erste Zeile der README.md
2. **README.md im Name-Verzeichnis**: Als Fallback
3. **Pfad-Info**: `Jahr: 2024 | Name: Max Mustermann | Projekt: Urlaub Mallorca`
4. **Final-Fallback**: Verzeichnis-Pfad

### Name
1. **Parameter**: `--name` (überschreibt alles)
2. **Name-Verzeichnis**: Aus dem Namen-Verzeichnis (z.B. `Max_Mustermann`)
3. **Fallback**: Leer

## Unterstützte Formate

- **Bilder**: `.jpg`, `.jpeg`, `.png`, `.gif`, `.bmp`, `.webp`, `.tiff`, `.tif`
- **Max. Größe**: 10MB pro Datei

## Beispiel-Output

```
12:34:56 - __main__ - INFO - Teste Verbindung zu http://localhost:5000...
12:34:56 - __main__ - INFO - ✅ Backend erreichbar
12:34:56 - __main__ - INFO - Scanne Verzeichnis: /home/user/photos
12:34:56 - __main__ - INFO - 📁 25 Bilder gefunden
12:34:56 - __main__ - INFO - 🚀 Starte Upload...
12:34:56 - __main__ - INFO - Starte Upload von 25 Bildern in 5er Batches
12:34:57 - __main__ - INFO - Chunk erfolgreich: 5 Bilder
12:34:57 - __main__ - INFO - Progress: 20.0% (5/25)
12:34:58 - __main__ - INFO - Chunk erfolgreich: 5 Bilder
12:34:58 - __main__ - INFO - Progress: 40.0% (10/25)
...
12:35:01 - __main__ - INFO - 📊 Upload abgeschlossen:
12:35:01 - __main__ - INFO -   ✅ Erfolgreich: 25
12:35:01 - __main__ - INFO -   ❌ Fehlgeschlagen: 0
```

## Verzeichnis-Struktur Beispiele

### Input-Struktur: `Photos/Jahr/Name/Projekt/dateiname.endung`

**Linux/macOS:**
```
photos/
├── 2024/
│   ├── Max_Mustermann/
│   │   ├── Urlaub_Mallorca/
│   │   │   ├── README.md
│   │   │   ├── sonnenuntergang.jpg
│   │   │   └── strand_spaziergang.jpg
│   │   └── Hochzeit_Anna/
│   │       ├── README.md
│   │       ├── zeremonie.jpg
│   │       └── party.jpg
│   └── Anna_Schmidt/
│       └── Architektur_Berlin/
│           ├── README.md
│           └── brandenburger_tor.jpg
└── 2023/
    └── Familie_Mueller/
        └── Weihnachten/
            ├── README.md
            └── weihnachtsbaum.jpg
```

**Windows:**
```
C:\Users\lotzm\Nextcloud2\HH DropFolder with quota\=NutzerBildUploads=\
├── 2024\
│   ├── Familie_Schmidt\
│   │   ├── Urlaub_Toskana\
│   │   │   ├── README.md
│   │   │   ├── florenz_dom.jpg
│   │   │   └── vineyard_sunset.jpg
│   │   └── Geburtstag_Opa\
│   │       ├── README.md
│   │       ├── torte.jpg
│   │       └── familie_komplett.jpg
│   └── Max_Mueller\
│       └── Business_Frankfurt\
│           ├── README.md
│           └── skyline_evening.jpg
└── 2023\
    └── Events\
        └── Hochzeit_Sarah\
            ├── README.md
            └── kirche_aussen.jpg
```

### README.md Beispiel
```markdown
# Urlaub Mallorca

Traumhafter Urlaub auf Mallorca mit Sonne, Strand und entspannten Momenten am Pool.

## Details
- Jahr: 2024
- Fotograf: Max Mustermann  
- Projekt: Urlaub Mallorca
```

### Extrahierte Metadaten
```json
{
  "jahr": "2024",
  "titel": "Urlaub Mallorca",
  "beschreibung": "Traumhafter Urlaub auf Mallorca mit Sonne, Strand und entspannten Momenten am Pool.",
  "name": "Max Mustermann"
}
```

## Error-Handling

- **Connection-Timeout**: 10s für Backend-Test, 60s für Upload
- **File-Errors**: Automatisches Skip von beschädigten Bildern
- **Chunk-Failures**: Einzelne Chunks können fehlschlagen ohne Abbruch
- **Retry-Logic**: Verwendet Session für Connection-Reuse

## Cross-Platform Support

- **✅ Windows**: Vollständige Unterstützung für Windows-Pfade und Leerzeichen
- **✅ Linux/macOS**: Native Unix-Pfad Unterstützung  
- **✅ Nextcloud/Dropbox**: Funktioniert mit Sync-Ordnern
- **✅ Netzwerk-Pfade**: UNC-Pfade (`\\server\share`) unterstützt

### Windows-spezifische Hinweise
```bash
# Absolute Pfade mit Leerzeichen in Anführungszeichen
python batch_uploader.py "C:\Users\lotzm\Nextcloud2\HH DropFolder with quota\=NutzerBildUploads="

# Escape-Zeichen für Sonderzeichen im Pfad
python batch_uploader.py "D:\Photos\Familie Schmidt\2024 Events"

# UNC-Netzwerk-Pfade
python batch_uploader.py "\\\\nas-server\\photos\\2024" --verbose
```

## Performance

- **Single-Group Upload**: Alle Bilder einer Session gehören zu EINER Gruppe (Fixed!)
- **Session-Reuse**: HTTP-Connections werden wiederverwendet
- **Memory-Effizient**: Bilder werden einzeln gelesen und direkt uploaded
- **Path-Performance**: `pathlib.Path.resolve()` für optimale Pfad-Verarbeitung
- **Robuste Uploads**: Längere Timeouts für große Batches (120s)

## Troubleshooting

### Backend nicht erreichbar
```bash
### Backend Status prüfen
```bash
# Prüfe Backend-Status
curl http://localhost:5000/groups

# Backend starten
cd ../
./prod.sh
```

### EXIF-Fehler
```bash
# Pillow neu installieren
pip install --upgrade Pillow
```

### Performance bei großen Batches
```bash
# Kleinere Chunk-Size verwenden
python batch_uploader.py /photos --chunk-size 3

# Progress verfolgen
python batch_uploader.py /photos --verbose
```