Initialer Commit
This commit is contained in:
commit
00321817dc
19
.gitignore
vendored
Normal file
19
.gitignore
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
# Build- und Cache-Ordner ignorieren
|
||||
__pycache__/
|
||||
upload/
|
||||
logs/
|
||||
build/
|
||||
dist/
|
||||
/pyUpload.*/
|
||||
Output/
|
||||
|
||||
# Virtuelle Umgebung ignorieren (falls vorhanden)
|
||||
.venv/
|
||||
.env/
|
||||
.idea/
|
||||
.vscode/
|
||||
*.pem
|
||||
|
||||
# PyInstaller-exe-Dateien ignorieren
|
||||
*.spec
|
||||
pyUpload.exe
|
35
Makefile
Normal file
35
Makefile
Normal file
@ -0,0 +1,35 @@
|
||||
.PHONY: exe release clean
|
||||
|
||||
# Variablen
|
||||
PYTHON = python3
|
||||
SCRIPT = pyUpload.py
|
||||
EXE_NAME = pyUpload
|
||||
BUILD_DIR = build
|
||||
DIST_DIR = release
|
||||
REQ_FILE = requirements.txt
|
||||
|
||||
exe:
|
||||
@echo "Erzeuge ausführbare Datei..."
|
||||
@mkdir -p $(BUILD_DIR)
|
||||
pyinstaller --onefile --add-data "template.html;." --add-data "success.html;." --add-data "favicon.ico;." --windowed --icon favicon.ico --name $(EXE_NAME) $(SCRIPT)
|
||||
@mv dist/$(EXE_NAME) $(BUILD_DIR)/
|
||||
@echo "Erstellung abgeschlossen: $(BUILD_DIR)/$(EXE_NAME)"
|
||||
|
||||
release: exe
|
||||
@echo "Erstelle Release-Paket..."
|
||||
@mkdir -p $(DIST_DIR)
|
||||
@cp $(BUILD_DIR)/$(EXE_NAME) $(DIST_DIR)/
|
||||
@cp $(REQ_FILE) $(DIST_DIR)/
|
||||
@cp template.html success.html favicon.ico $(DIST_DIR)/
|
||||
@echo "Release-Paket bereit in $(DIST_DIR)"
|
||||
|
||||
zip: release
|
||||
@echo "Erstelle ZIP-Archiv..."
|
||||
@cd $(DIST_DIR) && zip -r ../$(ZIP_NAME) $(EXE_NAME) template.html success.html favicon.ico
|
||||
@echo "ZIP-Archiv erstellt: $(ZIP_NAME)"
|
||||
|
||||
clean:
|
||||
@echo "Bereinige Projektverzeichnis..."
|
||||
@rm -rf $(BUILD_DIR) $(DIST_DIR) build dist __pycache__ *.spec
|
||||
@echo "Bereinigung abgeschlossen."
|
||||
|
4
Tagebuch.md
Normal file
4
Tagebuch.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Entwicklertagebuch
|
||||
|
||||
## 08.03.25
|
||||
Heute habe ich die mit innoSetup auf einem Rechner installiert auf dem überhaupt kein Python installiert war und dies funktionierte nicht. Klar auch, die venv Umgebung setzt eine Python Installation vorraus und arbeitet mit absoluten Pfaden. Der nächste Versuch wird mit einer portablen Python Version durchgeführt.
|
70
_static/Tagebuch
Normal file
70
_static/Tagebuch
Normal file
@ -0,0 +1,70 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Entwicklertagebuch - </title>
|
||||
<meta name="description" content="08.03.25 Heute habe ich die mit innoSetup auf einem Rechner installiert auf dem überhaupt kein Python installiert war und dies funktionierte nicht. Klar…">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
|
||||
<style>
|
||||
body{font-family:Helvetica,sans-serif;margin:0}
|
||||
header,main,footer{padding:2em}
|
||||
header{background:darkslategray} header a{color:white;text-decoration:none}
|
||||
h1{margin-top:0} main{max-width:60em}
|
||||
</style>
|
||||
|
||||
<link rel="canonical" href="/Tagebuch">
|
||||
<link rel="alternate" href="/feed.xml" type="application/rss+xml" title="RSS">
|
||||
|
||||
</head>
|
||||
<body class="page page__Tagebuch">
|
||||
<header><a href="/"></a></header>
|
||||
<main class="content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h1>Entwicklertagebuch</h1>
|
||||
|
||||
|
||||
<h2>08.03.25</h2>
|
||||
|
||||
<p>Heute habe ich die mit innoSetup auf einem Rechner installiert auf dem überhaupt kein Python installiert war und dies funktionierte nicht. Klar auch, die venv Umgebung setzt eine Python Installation vorraus und arbeitet mit absoluten Pfaden. Der nächste Versuch wird mit einer portablen Python Version durchgeführt. </p>
|
||||
|
||||
|
||||
|
||||
|
||||
<ul class="page__list">
|
||||
|
||||
<li><a href="/build-infos">
|
||||
## exe erstellen:
|
||||
|
||||
### pyinstaller
|
||||
|
||||
pip install pyinstaller
|
||||
pyinstaller --onefile --add-data "template.html;." --add-data "success.html;." --add-data "favicon.ico;." --windowed --icon favicon.ico pyUpload.py
|
||||
pyinstaller --add-data "template.html;." --add-data "success.html;." --add-data "favicon.ico;." --windowed --icon favicon.ico pyUpload.py
|
||||
|
||||
### nuitka
|
||||
|
||||
python setup.py build
|
||||
nuitka --standalone --onefile --enable-plugin=tk-inter --windows-console-mode=disable --windows-icon-from-ico=favicon.ico pyUpload.py
|
||||
|
||||
|
||||
|
||||
## requirements.txt:
|
||||
|
||||
pipreqs . --force</a></li>
|
||||
|
||||
<li><a href="/info">#pyUpload - Sicherer Datei-Upload-Server für eine einfache und sichere Dateiübertragung</a></li>
|
||||
|
||||
<li><a href="/dev/README">#pyUpload - Sicherer Datei-Upload-Server für eine einfache und sichere Dateiübertragung</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
</main>
|
||||
<footer><p>© </footer>
|
||||
</body>
|
||||
</html>
|
BIN
_static/Tagebuch.br
Normal file
BIN
_static/Tagebuch.br
Normal file
Binary file not shown.
86
_static/build-infos
Normal file
86
_static/build-infos
Normal file
@ -0,0 +1,86 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>
|
||||
## exe erstellen:
|
||||
|
||||
### pyinstaller
|
||||
|
||||
pip install pyinstaller
|
||||
pyinstaller --onefile --add-data "template.html;." --add-data "success.html;." --add-data "favicon.ico;." --windowed --icon favicon.ico pyUpload.py
|
||||
pyinstaller --add-data "template.html;." --add-data "success.html;." --add-data "favicon.ico;." --windowed --icon favicon.ico pyUpload.py
|
||||
|
||||
### nuitka
|
||||
|
||||
python setup.py build
|
||||
nuitka --standalone --onefile --enable-plugin=tk-inter --windows-console-mode=disable --windows-icon-from-ico=favicon.ico pyUpload.py
|
||||
|
||||
|
||||
|
||||
## requirements.txt:
|
||||
|
||||
pipreqs . --force - </title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
|
||||
<style>
|
||||
body{font-family:Helvetica,sans-serif;margin:0}
|
||||
header,main,footer{padding:2em}
|
||||
header{background:darkslategray} header a{color:white;text-decoration:none}
|
||||
h1{margin-top:0} main{max-width:60em}
|
||||
</style>
|
||||
|
||||
<link rel="canonical" href="/build-infos">
|
||||
<link rel="alternate" href="/feed.xml" type="application/rss+xml" title="RSS">
|
||||
|
||||
</head>
|
||||
<body class="page page__build-infos">
|
||||
<header><a href="/"></a></header>
|
||||
<main class="content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h1>
|
||||
## exe erstellen:
|
||||
|
||||
### pyinstaller
|
||||
|
||||
pip install pyinstaller
|
||||
pyinstaller --onefile --add-data "template.html;." --add-data "success.html;." --add-data "favicon.ico;." --windowed --icon favicon.ico pyUpload.py
|
||||
pyinstaller --add-data "template.html;." --add-data "success.html;." --add-data "favicon.ico;." --windowed --icon favicon.ico pyUpload.py
|
||||
|
||||
### nuitka
|
||||
|
||||
python setup.py build
|
||||
nuitka --standalone --onefile --enable-plugin=tk-inter --windows-console-mode=disable --windows-icon-from-ico=favicon.ico pyUpload.py
|
||||
|
||||
|
||||
|
||||
## requirements.txt:
|
||||
|
||||
pipreqs . --force</h1>
|
||||
|
||||
|
||||
<p></p>
|
||||
|
||||
|
||||
|
||||
|
||||
<ul class="page__list">
|
||||
|
||||
<li><a href="/Tagebuch">Entwicklertagebuch</a></li>
|
||||
|
||||
<li><a href="/info">#pyUpload - Sicherer Datei-Upload-Server für eine einfache und sichere Dateiübertragung</a></li>
|
||||
|
||||
<li><a href="/dev/README">#pyUpload - Sicherer Datei-Upload-Server für eine einfache und sichere Dateiübertragung</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
</main>
|
||||
<footer><p>© </footer>
|
||||
</body>
|
||||
</html>
|
BIN
_static/build-infos.br
Normal file
BIN
_static/build-infos.br
Normal file
Binary file not shown.
177
_static/info
Normal file
177
_static/info
Normal file
@ -0,0 +1,177 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>#pyUpload - Sicherer Datei-Upload-Server für eine einfache und sichere Dateiübertragung - </title>
|
||||
<meta name="description" content="Beschreibung pyUpload ist eine leistungsstarke und dennoch einfache Lösung für den sicheren Datei-Upload über HTTPS. Dieses Programm eignet sich ideal,…">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
|
||||
<style>
|
||||
body{font-family:Helvetica,sans-serif;margin:0}
|
||||
header,main,footer{padding:2em}
|
||||
header{background:darkslategray} header a{color:white;text-decoration:none}
|
||||
h1{margin-top:0} main{max-width:60em}
|
||||
</style>
|
||||
|
||||
<link rel="canonical" href="/info">
|
||||
<link rel="alternate" href="/feed.xml" type="application/rss+xml" title="RSS">
|
||||
|
||||
</head>
|
||||
<body class="page page__info">
|
||||
<header><a href="/"></a></header>
|
||||
<main class="content">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h1>#pyUpload - Sicherer Datei-Upload-Server für eine einfache und sichere Dateiübertragung</h1>
|
||||
|
||||
|
||||
<h3>Beschreibung</h3>
|
||||
|
||||
<p>pyUpload ist eine leistungsstarke und dennoch einfache Lösung für den sicheren Datei-Upload über HTTPS. Dieses Programm eignet sich ideal, um Dateien schnell und unkompliziert von einem Smartphone oder einem anderen Gerät auf einen Computer zu übertragen. </p>
|
||||
|
||||
<p>Anstatt zusätzliche Apps oder USB-Kabel zu nutzen, kann der Benutzer den Server starten, den automatisch generierten QR-Code mit dem Smartphone scannen und die Dateien direkt über die Weboberfläche hochladen. Der Computer speichert die hochgeladenen Dateien strukturiert in individuellen Verzeichnissen für jedes Gerät.</p>
|
||||
|
||||
<p>Zusätzlich erstellt pyUpload bei Bedarf automatisch ein selbstsigniertes SSL-Zertifikat, um eine verschlüsselte Verbindung sicherzustellen. Damit bleibt die Dateiübertragung geschützt und zuverlässig.</p>
|
||||
|
||||
<h3>Download</h3>
|
||||
|
||||
<ul>
|
||||
<li><strong>Portabel für Windows als .zip</strong>
|
||||
[download id="2323"]</li>
|
||||
</ul>
|
||||
|
||||
<blockquote>
|
||||
<p>Aktuell ist der Download der portablen und Compilierten Version gesperrt da es von diversen Virenscannern als Bedrohung eingestuft wird. Bei Interesse ist das Programm aktuell nur auf Anfrage per eMail erhältlich. In Kürze erfolgt eine Veröffentlichung inklusive Code auf GitHub.</p>
|
||||
</blockquote>
|
||||
|
||||
<h3>Features – Die Vorteile von pyUpload auf einen Blick</h3>
|
||||
|
||||
<ul>
|
||||
<li><strong>Sichere Dateiübertragung per HTTPS</strong> – Alle Daten werden verschlüsselt übertragen.</li>
|
||||
<li><strong>Automatische Erstellung eines selbstsignierten SSL-Zertifikats</strong> – Keine zusätzliche Konfiguration notwendig.</li>
|
||||
<li><strong>Intuitive, webbasierte Benutzeroberfläche</strong> – Einfach zu bedienen, keine Installation erforderlich.</li>
|
||||
<li><strong>Strukturierte Speicherung</strong> – Dateien werden in client-spezifischen Verzeichnissen gespeichert.</li>
|
||||
<li><strong>Zentralisierte und client-spezifische Logging-Funktion</strong> – Detaillierte Nachverfolgung aller Uploads.</li>
|
||||
<li><strong>Flexible Nutzung mit oder ohne GUI</strong> – Start als Desktop-Anwendung oder reine Konsolen-Version möglich.</li>
|
||||
<li><strong>Schnelle Einrichtung</strong> – Download, Entpacken und sofort loslegen!</li>
|
||||
</ul>
|
||||
|
||||
<h3>Installationsanleitung – So startest du pyUpload</h3>
|
||||
|
||||
<p>Es gibt zwei Möglichkeiten, pyUpload zu nutzen: Entweder die manuelle Installation oder die Nutzung einer vorgefertigten, ausführbaren Version.</p>
|
||||
|
||||
<h4>1. Nutzung der fertigen Download-Version</h4>
|
||||
|
||||
<p>Falls du keine Python-Installation benötigst, kannst du die vorgefertigte <strong>ZIP-Version</strong> von pyUpload herunterladen. Diese enthält bereits alle notwendigen Dateien und ist sofort einsatzbereit.</p>
|
||||
|
||||
<ol>
|
||||
<li>Lade die neueste <strong>pyUpload.zip</strong> von der offiziellen Website herunter.</li>
|
||||
<li>Entpacke die ZIP-Datei in einen beliebigen Ordner.</li>
|
||||
<li>Starte die enthaltene <code>pyUpload.exe</code>.</li>
|
||||
<li>Falls die grafische Benutzeroberfläche nicht benötigt wird, kann die <code>pyUpload.exe</code> direkt in der Konsole mit <code>--nogui</code> gestartet werden:
|
||||
<code>sh
|
||||
pyUpload.exe --nogui
|
||||
</code></li>
|
||||
<li>Eine Übersicht aller verfügbaren Befehle und Optionen erhältst du mit:
|
||||
<code>sh
|
||||
pyUpload.exe --help
|
||||
</code></li>
|
||||
</ol>
|
||||
|
||||
<h4>2. Manuelle Installation für Python-Nutzer</h4>
|
||||
|
||||
<ol>
|
||||
<li>Stelle sicher, dass <strong>Python 3</strong> auf deinem System installiert ist.</li>
|
||||
<li>Installiere alle benötigten Abhängigkeiten mit folgendem Befehl:
|
||||
<code>sh
|
||||
pip install -r requirements.txt
|
||||
</code></li>
|
||||
<li>Starte den Server mit:
|
||||
<code>sh
|
||||
python pyUpload.py
|
||||
</code></li>
|
||||
<li>Falls du keine grafische Benutzeroberfläche benötigst, kannst du den Server im Konsolenmodus starten:
|
||||
<code>sh
|
||||
python pyUpload.py --nogui
|
||||
</code></li>
|
||||
</ol>
|
||||
|
||||
<h3>Zugriff auf die Weboberfläche</h3>
|
||||
|
||||
<ul>
|
||||
<li>Sobald der Server läuft, kann er über die lokale IP-Adresse aufgerufen werden:
|
||||
<code>
|
||||
https://<server-ip>:4443
|
||||
</code></li>
|
||||
<li>Falls die GUI-Version gestartet wurde, erscheint ein <strong>QR-Code</strong>, der die Verbindungsadresse enthält. Dies ermöglicht eine einfache Verbindung mit Smartphones und Tablets.</li>
|
||||
</ul>
|
||||
|
||||
<h3>Datei-Upload leicht gemacht – So funktioniert es</h3>
|
||||
|
||||
<ol>
|
||||
<li>Öffne die <strong>Weboberfläche</strong> im Browser.</li>
|
||||
<li>Wähle die gewünschte <strong>Datei aus</strong> und klicke auf <strong>„Hochladen“</strong>.</li>
|
||||
<li>Nach erfolgreichem Upload erscheint eine <strong>Bestätigungsseite</strong>, die den Abschluss der Übertragung bestätigt.</li>
|
||||
</ol>
|
||||
|
||||
<h3>SSL-Zertifikatswarnung in Browsern umgehen</h3>
|
||||
|
||||
<p>Da pyUpload ein <strong>selbstsigniertes SSL-Zertifikat</strong> nutzt, kann es beim ersten Zugriff zu einer Warnung des Browsers kommen. Um die verschlüsselte Verbindung zu akzeptieren, gibt es zwei Möglichkeiten:</p>
|
||||
|
||||
<ul>
|
||||
<li>In den meisten Browsern gibt es eine Option wie <strong>„Erweitert“</strong> oder <strong>„Trotzdem fortfahren“</strong>, um die Warnung zu übergehen.</li>
|
||||
<li>Alternativ kann das Zertifikat <strong>manuell importiert und als vertrauenswürdig markiert</strong> werden, um künftige Warnmeldungen zu vermeiden.</li>
|
||||
</ul>
|
||||
|
||||
<h3>Logging und Fehlerbehandlung – Transparenz und Kontrolle</h3>
|
||||
|
||||
<ul>
|
||||
<li>Alle <strong>Uploads und Anfragen</strong> werden in <strong>zentralen sowie client-spezifischen Logdateien</strong> gespeichert. Diese befinden sich im <code>logs/</code>-Verzeichnis.</li>
|
||||
<li>Falls während der Nutzung von pyUpload <strong>Probleme auftreten</strong>, bietet ein Blick in diese Logdateien wertvolle Hinweise zur Fehlerbehebung.</li>
|
||||
</ul>
|
||||
|
||||
<h3>Lizenz und Autor</h3>
|
||||
|
||||
<ul>
|
||||
<li><strong>Entwickelt von Adam Skotarczak (C) 2025</strong>.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
<ul class="page__list">
|
||||
|
||||
<li><a href="/Tagebuch">Entwicklertagebuch</a></li>
|
||||
|
||||
<li><a href="/build-infos">
|
||||
## exe erstellen:
|
||||
|
||||
### pyinstaller
|
||||
|
||||
pip install pyinstaller
|
||||
pyinstaller --onefile --add-data "template.html;." --add-data "success.html;." --add-data "favicon.ico;." --windowed --icon favicon.ico pyUpload.py
|
||||
pyinstaller --add-data "template.html;." --add-data "success.html;." --add-data "favicon.ico;." --windowed --icon favicon.ico pyUpload.py
|
||||
|
||||
### nuitka
|
||||
|
||||
python setup.py build
|
||||
nuitka --standalone --onefile --enable-plugin=tk-inter --windows-console-mode=disable --windows-icon-from-ico=favicon.ico pyUpload.py
|
||||
|
||||
|
||||
|
||||
## requirements.txt:
|
||||
|
||||
pipreqs . --force</a></li>
|
||||
|
||||
<li><a href="/dev/README">#pyUpload - Sicherer Datei-Upload-Server für eine einfache und sichere Dateiübertragung</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
</main>
|
||||
<footer><p>© </footer>
|
||||
</body>
|
||||
</html>
|
BIN
_static/info.br
Normal file
BIN
_static/info.br
Normal file
Binary file not shown.
BIN
assets/favicon.ico
Normal file
BIN
assets/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 122 KiB |
BIN
assets/pyUpload-Logo.webp
Normal file
BIN
assets/pyUpload-Logo.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 173 KiB |
BIN
assets/screenshot_gui_v1.2.1.png
Normal file
BIN
assets/screenshot_gui_v1.2.1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 51 KiB |
BIN
backup/pyUpload_0.1.0.zip
Normal file
BIN
backup/pyUpload_0.1.0.zip
Normal file
Binary file not shown.
19
build-infos.md
Normal file
19
build-infos.md
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
## exe erstellen:
|
||||
|
||||
### pyinstaller
|
||||
|
||||
pip install pyinstaller
|
||||
pyinstaller --onefile --add-data "template.html;." --add-data "success.html;." --add-data "favicon.ico;." --windowed --icon favicon.ico pyUpload.py
|
||||
pyinstaller --add-data "template.html;." --add-data "success.html;." --add-data "favicon.ico;." --windowed --icon favicon.ico pyUpload.py
|
||||
|
||||
### nuitka
|
||||
|
||||
python setup.py build
|
||||
nuitka --standalone --onefile --enable-plugin=tk-inter --windows-console-mode=disable --windows-icon-from-ico=favicon.ico pyUpload.py
|
||||
|
||||
|
||||
|
||||
## requirements.txt:
|
||||
|
||||
pipreqs . --force
|
67
build.bat
Normal file
67
build.bat
Normal file
@ -0,0 +1,67 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
:: Variablen
|
||||
set SCRIPT=pyUpload.py
|
||||
set EXE_NAME=pyUpload.exe
|
||||
set BUILD_DIR=build
|
||||
set DIST_DIR=release
|
||||
set ZIP_NAME=pyUpload.zip
|
||||
set REQ_FILE=requirements.txt
|
||||
|
||||
:: Liste von Dateien/Ordnern, die beim "clean" entfernt werden sollen
|
||||
set DELETE_LIST=build dist __pycache__ *.spec *.zip temp_* logs\* cache\* pyUpload.build\* pyUpload.dist\* upload\* *.pem
|
||||
|
||||
:: Menü anzeigen
|
||||
echo Wähle eine Option:
|
||||
echo 1 - Erstelle ausführbare Datei (exe 1)
|
||||
echo 2 - Erstelle Release-Paket (release 1+2)
|
||||
echo 3 - Erstelle ZIP-Archiv (zip 1+2+3)
|
||||
echo 4 - Aufraeumen (clean)
|
||||
set /p CHOICE=Eingabe (1-4):
|
||||
|
||||
if "%CHOICE%"=="1" goto exe
|
||||
if "%CHOICE%"=="2" goto release
|
||||
if "%CHOICE%"=="3" goto zip
|
||||
if "%CHOICE%"=="4" goto clean
|
||||
echo Ungültige Eingabe!
|
||||
exit /b
|
||||
|
||||
:exe
|
||||
echo Erzeuge ausführbare Datei...
|
||||
mkdir %BUILD_DIR% 2>nul
|
||||
pyinstaller --onefile --add-data "template.html;." --add-data "success.html;." --add-data "favicon.ico;." --windowed --icon favicon.ico --name %EXE_NAME% %SCRIPT%
|
||||
move dist\%EXE_NAME% %BUILD_DIR%\
|
||||
echo Erstellung abgeschlossen: %BUILD_DIR%\%EXE_NAME%
|
||||
exit /b
|
||||
|
||||
:release
|
||||
call :exe
|
||||
echo Erstelle Release-Paket...
|
||||
mkdir %DIST_DIR% 2>nul
|
||||
copy %BUILD_DIR%\%EXE_NAME% %DIST_DIR%\
|
||||
copy %REQ_FILE% %DIST_DIR%\
|
||||
copy template.html success.html favicon.ico %DIST_DIR%\
|
||||
echo Release-Paket bereit in %DIST_DIR%
|
||||
exit /b
|
||||
|
||||
:zip
|
||||
call :release
|
||||
echo Erstelle ZIP-Archiv...
|
||||
powershell Compress-Archive -Path "%DIST_DIR%\%EXE_NAME%", "%DIST_DIR%\template.html", "%DIST_DIR%\success.html", "%DIST_DIR%\favicon.ico" -DestinationPath "%ZIP_NAME%"
|
||||
echo ZIP-Archiv erstellt: %ZIP_NAME%
|
||||
exit /b
|
||||
|
||||
:clean
|
||||
echo Bereinige Projektverzeichnis...
|
||||
|
||||
:: Durchläuft alle Dateien/Ordner in DELETE_LIST
|
||||
for %%F in (%DELETE_LIST%) do (
|
||||
if exist %%F (
|
||||
echo Entferne: %%F
|
||||
rmdir /s /q %%F 2>nul || del /q %%F 2>nul
|
||||
)
|
||||
)
|
||||
|
||||
echo Bereinigung abgeschlossen.
|
||||
exit /b
|
6
desktop.ini
Normal file
6
desktop.ini
Normal file
@ -0,0 +1,6 @@
|
||||
[.ShellClassInfo]
|
||||
IconResource=C:\Users\adam\Documents\Projekte\pyUpload\assets\favicon.ico,0
|
||||
[ViewState]
|
||||
Mode=
|
||||
Vid=
|
||||
FolderType=Documents
|
10
dev/LICENSE
Normal file
10
dev/LICENSE
Normal file
@ -0,0 +1,10 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Adam Scotarczak (adam@skotarczak.net) - ionivation.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
93
dev/README.md
Normal file
93
dev/README.md
Normal file
@ -0,0 +1,93 @@
|
||||
## pyUpload - Sicherer Datei-Upload-Server für eine einfache und sichere Dateiübertragung
|
||||
|
||||
### Beschreibung
|
||||
|
||||
pyUpload ist eine leistungsstarke und dennoch einfache Lösung für den sicheren Datei-Upload über HTTPS. Es richtet sich an Privatnutzer, die eine schnelle Möglichkeit suchen, Dateien zwischen Geräten zu übertragen, sowie an Unternehmen oder Teams, die eine sichere Lösung für den internen Datenaustausch benötigen. Dieses Programm eignet sich ideal, um Dateien schnell und unkompliziert von einem Smartphone oder einem anderen Gerät auf einen Computer zu übertragen.
|
||||
|
||||
Anstatt zusätzliche Apps oder USB-Kabel zu nutzen, kann der Benutzer den Server starten, den automatisch generierten QR-Code mit dem Smartphone scannen und die Dateien direkt über die Weboberfläche hochladen. Der Computer speichert die hochgeladenen Dateien strukturiert in individuellen Verzeichnissen für jedes Gerät.
|
||||
|
||||
Zusätzlich erstellt pyUpload bei Bedarf automatisch ein selbstsigniertes SSL-Zertifikat, um eine verschlüsselte Verbindung sicherzustellen. Damit bleibt die Dateiübertragung geschützt und zuverlässig.
|
||||
|
||||
### Features – Die Vorteile von pyUpload auf einen Blick
|
||||
|
||||
- **Sichere Dateiübertragung per HTTPS** – Alle Daten werden verschlüsselt übertragen.
|
||||
- **Automatische Erstellung eines selbstsignierten SSL-Zertifikats** – Keine zusätzliche Konfiguration notwendig.
|
||||
- **Intuitive, webbasierte Benutzeroberfläche** – Einfach zu bedienen, keine Installation erforderlich.
|
||||
- **Strukturierte Speicherung** – Dateien werden in client-spezifischen Verzeichnissen gespeichert.
|
||||
- **Zentralisierte und client-spezifische Logging-Funktion** – Detaillierte Nachverfolgung aller Uploads.
|
||||
- **Flexible Nutzung mit oder ohne GUI** – Start als Desktop-Anwendung oder reine Konsolen-Version möglich.
|
||||
- **Schnelle Einrichtung** – Download, Entpacken und sofort loslegen!
|
||||
|
||||
### Installationsanleitung – So startest du pyUpload
|
||||
|
||||
Es gibt drei Möglichkeiten, pyUpload zu nutzen:
|
||||
- **Manuelle Installation** in einer vorhandenen Python-Umgebung, in der alle notwendigen Bibliotheken manuell installiert werden.
|
||||
- **Nutzung einer vorgefertigten, ausführbaren .exe (Windows) Version**, die mit pyinstaller kompiliert wurde.
|
||||
- **Nutzung in einer virtuellen Python-Umgebung**, die automatisch durch `install.bat` eingerichtet wird. Anschließend kann das Programm mit `start.bat` gestartet werden.
|
||||
|
||||
#### 1. Manuelle Installation für Python-Nutzer
|
||||
|
||||
1. Stelle sicher, dass **Python 3** auf deinem System installiert ist.
|
||||
2. Installiere alle benötigten Abhängigkeiten mit folgendem Befehl:
|
||||
```sh
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
3. Starte den Server mit:
|
||||
```sh
|
||||
python pyUpload.py
|
||||
```
|
||||
4. Falls du keine grafische Benutzeroberfläche benötigst, kannst du den Server im Konsolenmodus starten:
|
||||
```sh
|
||||
python pyUpload.py --nogui
|
||||
```
|
||||
|
||||
#### 2. Nutzung der fertigen .exe Download-Version
|
||||
|
||||
Falls du keine Python-Installation benötigst, kannst du die vorgefertigte **ZIP-Version** von pyUpload herunterladen. Diese enthält bereits alle notwendigen Dateien und ist sofort einsatzbereit.
|
||||
|
||||
1. Lade die neueste **pyUpload.zip** von der offiziellen Website herunter, inklusive virtueller Umgebung.
|
||||
2. Entpacke die ZIP-Datei in einen beliebigen Ordner.
|
||||
3. Starte die enthaltene `pyUpload.exe`.
|
||||
4. Falls die grafische Benutzeroberfläche nicht benötigt wird, kann die `pyUpload.exe` direkt in der Konsole mit `--nogui` gestartet werden:
|
||||
```sh
|
||||
pyUpload.exe --nogui
|
||||
```
|
||||
5. Eine Übersicht aller verfügbaren Befehle und Optionen erhältst du mit:
|
||||
```sh
|
||||
pyUpload.exe --help
|
||||
```
|
||||
|
||||
#### 3. Nutzung in virtueller Python-Umgebung
|
||||
|
||||
Lade die ZIP-Datei mit der virtuellen Installationsumgebung herunter und starte die `install.bat` durch Doppelklick. Es öffnet sich ein Konsolenfenster (CLI) und eine virtuelle Umgebung für pyUpload wird erstellt. Anschließend kann das Programm mit der `start.bat` gestartet werden. In der Grundeinstellung wird eine GUI mit QR-Code gestartet.
|
||||
|
||||
### Zugriff auf die Weboberfläche
|
||||
|
||||
- Sobald der Server läuft, kann er über die lokale IP-Adresse aufgerufen werden:
|
||||
```
|
||||
https://<server-ip>:4443
|
||||
```
|
||||
- Falls die GUI-Version gestartet wurde, erscheint ein **QR-Code**, der die Verbindungsadresse enthält. Dies ermöglicht eine einfache Verbindung mit Smartphones und Tablets.
|
||||
|
||||
### Datei-Upload leicht gemacht – So funktioniert es
|
||||
|
||||
1. Öffne die **Weboberfläche** im Browser.
|
||||
2. Wähle die gewünschte **Datei aus** und klicke auf **„Hochladen“**.
|
||||
3. Nach erfolgreichem Upload erscheint eine **Bestätigungsseite**, die den Abschluss der Übertragung bestätigt.
|
||||
|
||||
### SSL-Zertifikatswarnung in Browsern umgehen
|
||||
|
||||
Da pyUpload ein **selbstsigniertes SSL-Zertifikat** nutzt, wird es beim ersten Zugriff zu einer Warnung des Browsers kommen. Alternativ kann ein eigenes SSL-Zertifikat hinterlegt werden, indem die Zertifikats- und Schlüsseldateien `cert.pem` und `key.pem` durch eigene, signierte Zertifikate ersetzt werden. Um die verschlüsselte Verbindung zu akzeptieren, gibt es zwei Möglichkeiten:
|
||||
|
||||
- In den meisten Browsern gibt es eine Option wie **„Erweitert“** oder **„Trotzdem fortfahren“**, um die Warnung zu übergehen.
|
||||
- Alternativ kann das Zertifikat **manuell importiert und als vertrauenswürdig markiert** werden, um künftige Warnmeldungen zu vermeiden.
|
||||
|
||||
### Logging und Fehlerbehandlung – Transparenz und Kontrolle
|
||||
|
||||
- Alle **Uploads und Anfragen** werden in **zentralen sowie client-spezifischen Logdateien** gespeichert. Diese befinden sich im `logs/`-Verzeichnis.
|
||||
- Falls während der Nutzung von pyUpload **Probleme auftreten**, bietet ein Blick in diese Logdateien wertvolle Hinweise zur Fehlerbehebung.
|
||||
|
||||
### Lizenz und Autor
|
||||
|
||||
- **Entwickelt von Adam Skotarczak (C) 2025**.
|
||||
|
BIN
dev/favicon.ico
Normal file
BIN
dev/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 122 KiB |
54
dev/install.bat
Normal file
54
dev/install.bat
Normal file
@ -0,0 +1,54 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
:: Prüfen, ob Python installiert ist
|
||||
where python >nul 2>nul
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo Fehler: Python ist nicht installiert oder nicht im PATH!
|
||||
echo Bitte installiere Python und starte die Installation erneut.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
:: Python-Version prüfen (Mindestversion 3.8)
|
||||
for /f "tokens=2 delims= " %%v in ('python --version 2^>^&1') do set PYTHON_VERSION=%%v
|
||||
for /f "tokens=1,2 delims=." %%a in ("%PYTHON_VERSION%") do (
|
||||
if %%a LSS 3 (
|
||||
echo Fehler: Python 3.8 oder höher ist erforderlich!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
if %%a==3 if %%b LSS 8 (
|
||||
echo Fehler: Python 3.8 oder höher ist erforderlich!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
)
|
||||
|
||||
:: Virtuelle Umgebung erstellen, falls sie nicht existiert
|
||||
if not exist venv (
|
||||
echo Erstelle virtuelle Server-Umgebung ...
|
||||
python -m venv --copies venv
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo Fehler beim Erstellen der virtuellen Umgebung!
|
||||
pause
|
||||
exit /b 2
|
||||
)
|
||||
)
|
||||
|
||||
:: Aktivieren der virtuellen Umgebung
|
||||
call venv\Scripts\activate
|
||||
|
||||
:: Installieren der Abhängigkeiten
|
||||
echo Installiere Abhaengigkeiten aus dem Internet ...
|
||||
pip install --no-warn-script-location --disable-pip-version-check -r requirements.txt
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo Fehler beim Installieren der Abhaengigkeiten!
|
||||
pause
|
||||
exit /b 3
|
||||
)
|
||||
|
||||
:: Erfolgsmeldung
|
||||
echo.
|
||||
echo Installation abgeschlossen.
|
||||
timeout /t 3 >nul & exit /b 0
|
16
dev/pyUpload.bat
Normal file
16
dev/pyUpload.bat
Normal file
@ -0,0 +1,16 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
:: Prüfen, ob die virtuelle Umgebung existiert
|
||||
if not exist venv (
|
||||
echo Fehler: Die virtuelle Umgebung existiert nicht!
|
||||
echo Führe zuerst "install.bat" aus.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
|
||||
:: Aktivieren der virtuellen Umgebung
|
||||
call venv\Scripts\activate
|
||||
|
||||
:: Starte den Upload-Server
|
||||
python pyUpload.py
|
347
dev/pyUpload.py
Normal file
347
dev/pyUpload.py
Normal file
@ -0,0 +1,347 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# © 2025 Adam Skotarczak (adam@skotarczak.net)
|
||||
# Dieses Softwarepaket darf nicht ohne Genehmigung weiterverbreitet werden!
|
||||
# Version 1.2.2 (05.03.2025)
|
||||
|
||||
import os
|
||||
import sys
|
||||
import ssl
|
||||
import logging
|
||||
import socket
|
||||
import argparse
|
||||
import threading
|
||||
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
from cryptography import x509
|
||||
from cryptography.x509.oid import NameOID
|
||||
from cryptography.hazmat.primitives import hashes, serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Globale Konfigurationen & Verzeichnisse
|
||||
# -------------------------------------------------------------------
|
||||
UPLOAD_DIR = 'upload'
|
||||
LOG_DIR = 'logs'
|
||||
CERT_FILE = 'cert.pem'
|
||||
KEY_FILE = 'key.pem'
|
||||
CENTRAL_LOG_FILE = os.path.join(LOG_DIR, 'pyupload.log')
|
||||
|
||||
os.makedirs(UPLOAD_DIR, exist_ok=True)
|
||||
os.makedirs(LOG_DIR, exist_ok=True)
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s - %(message)s",
|
||||
handlers=[logging.FileHandler(CENTRAL_LOG_FILE), logging.StreamHandler()]
|
||||
)
|
||||
|
||||
central_logger = logging.getLogger("central_logger")
|
||||
client_loggers = {}
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# HTTP-Request-Handler
|
||||
# -------------------------------------------------------------------
|
||||
class SecureHTTPRequestHandler(BaseHTTPRequestHandler):
|
||||
def log_message(self, format, *args):
|
||||
"""Sammelt Log-Einträge in Client-spezifische Dateien und die Zentrale-Logdatei."""
|
||||
client_ip = self.client_address[0]
|
||||
message = format % args
|
||||
|
||||
# Einmalig pro Client-IP einen dedizierten Logger anlegen.
|
||||
if client_ip not in client_loggers:
|
||||
logger = logging.getLogger(f'client_{client_ip}')
|
||||
logger.setLevel(logging.INFO)
|
||||
client_log_file = os.path.join(LOG_DIR, f"{client_ip}.log")
|
||||
handler = logging.FileHandler(client_log_file)
|
||||
handler.setFormatter(logging.Formatter('%(asctime)s - %(message)s'))
|
||||
logger.addHandler(handler)
|
||||
client_loggers[client_ip] = logger
|
||||
|
||||
# In den Client-spezifischen Logger und in den zentralen Logger schreiben.
|
||||
client_loggers[client_ip].info(message)
|
||||
central_logger.info(f"{client_ip} - {message}")
|
||||
|
||||
def send_html_response(self, filename):
|
||||
"""Liefert eine HTML-Datei als HTTP-Response zurück."""
|
||||
try:
|
||||
with open(filename, "r", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
self.send_response(200)
|
||||
self.send_header('Content-type', 'text/html')
|
||||
self.end_headers()
|
||||
self.wfile.write(content.encode("utf-8"))
|
||||
except FileNotFoundError:
|
||||
self.send_error(500, "HTML-Template nicht gefunden")
|
||||
|
||||
def do_GET(self):
|
||||
"""Ausliefern der Upload-Seite (template.html)."""
|
||||
if self.path == '/':
|
||||
self.send_html_response("template.html")
|
||||
else:
|
||||
self.send_error(404, "Seite nicht gefunden")
|
||||
self.log_message('404 Not Found: %s', self.path)
|
||||
|
||||
def do_POST(self):
|
||||
"""Behandelt Datei-Uploads (multipart/form-data) direkt als Stream."""
|
||||
try:
|
||||
content_type = self.headers.get('Content-Type')
|
||||
content_length = int(self.headers.get('Content-Length', 0))
|
||||
|
||||
if not content_type or 'multipart/form-data' not in content_type:
|
||||
self.send_error(400, "Ungültiger Content-Type")
|
||||
self.log_message('400 Bad Request: Ungültiger Content-Type')
|
||||
return
|
||||
|
||||
if content_length == 0:
|
||||
self.send_error(400, "Leere Anfrage erhalten")
|
||||
self.log_message('400 Bad Request: Leere Anfrage')
|
||||
return
|
||||
|
||||
client_ip = self.client_address[0]
|
||||
client_upload_dir = os.path.join(UPLOAD_DIR, client_ip)
|
||||
os.makedirs(client_upload_dir, exist_ok=True)
|
||||
|
||||
boundary = content_type.split("boundary=")[-1].encode()
|
||||
raw_data = self.rfile.read(content_length)
|
||||
parts = raw_data.split(b"--" + boundary)
|
||||
|
||||
found_file = False
|
||||
|
||||
for part in parts:
|
||||
if b"Content-Disposition" in part:
|
||||
headers, file_data = part.split(b"\r\n\r\n", 1)
|
||||
filename_start = headers.find(b'filename="') + 10
|
||||
filename_end = headers.find(b'"', filename_start)
|
||||
filename = headers[filename_start:filename_end].decode()
|
||||
|
||||
if filename: # Falls tatsächlich ein Dateiname vorhanden ist
|
||||
file_path = os.path.join(client_upload_dir, os.path.basename(filename))
|
||||
with open(file_path, "wb") as f:
|
||||
# Entferne das trailing CRLF oder "--"
|
||||
f.write(file_data.rstrip(b"\r\n--"))
|
||||
self.log_message(f"Datei {filename} erfolgreich hochgeladen.")
|
||||
found_file = True
|
||||
|
||||
if not found_file:
|
||||
self.send_error(400, "Keine Datei im Upload enthalten")
|
||||
self.log_message('400 Bad Request: Keine Datei übermittelt')
|
||||
return
|
||||
|
||||
# Erfolgsseite senden
|
||||
self.send_html_response("success.html")
|
||||
|
||||
except Exception as e:
|
||||
self.log_message(f"Fehler: {e}")
|
||||
self.send_error(500, "Interner Serverfehler")
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# HTTPS-Server-Setup
|
||||
# -------------------------------------------------------------------
|
||||
def generate_self_signed_cert(cert_file, key_file):
|
||||
"""Erzeugt ein selbstsigniertes SSL-Zertifikat, falls keines vorhanden ist."""
|
||||
key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
|
||||
subject = issuer = x509.Name([
|
||||
x509.NameAttribute(NameOID.COUNTRY_NAME, "DE"),
|
||||
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Berlin"),
|
||||
x509.NameAttribute(NameOID.LOCALITY_NAME, "Berlin"),
|
||||
x509.NameAttribute(NameOID.ORGANIZATION_NAME, "ionivation.com"),
|
||||
x509.NameAttribute(NameOID.COMMON_NAME, "localhost.lan"),
|
||||
])
|
||||
cert = (
|
||||
x509.CertificateBuilder()
|
||||
.subject_name(subject)
|
||||
.issuer_name(issuer)
|
||||
.public_key(key.public_key())
|
||||
.serial_number(x509.random_serial_number())
|
||||
.not_valid_before(datetime.now(timezone.utc))
|
||||
.not_valid_after(datetime.now(timezone.utc) + timedelta(days=365))
|
||||
.add_extension(
|
||||
x509.SubjectAlternativeName([x509.DNSName("localhost")]),
|
||||
critical=False
|
||||
)
|
||||
.sign(key, hashes.SHA256())
|
||||
)
|
||||
|
||||
with open(cert_file, "wb") as f:
|
||||
f.write(cert.public_bytes(serialization.Encoding.PEM))
|
||||
with open(key_file, "wb") as f:
|
||||
f.write(key.private_bytes(
|
||||
encoding=serialization.Encoding.PEM,
|
||||
format=serialization.PrivateFormat.TraditionalOpenSSL,
|
||||
encryption_algorithm=serialization.NoEncryption()
|
||||
))
|
||||
|
||||
def get_server_ip():
|
||||
"""Bestimmt die lokale IP-Adresse, um sie z.B. für den QR-Code zu nutzen."""
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
try:
|
||||
s.connect(("8.8.8.8", 80))
|
||||
ip = s.getsockname()[0]
|
||||
except Exception:
|
||||
ip = "127.0.0.1"
|
||||
finally:
|
||||
s.close()
|
||||
return ip
|
||||
|
||||
def create_https_server(port, handler_class=SecureHTTPRequestHandler):
|
||||
"""Erzeugt ein HTTPS-Serverobjekt (aber startet ihn noch nicht)."""
|
||||
if not os.path.exists(CERT_FILE) or not os.path.exists(KEY_FILE):
|
||||
print("SSL-Zertifikat nicht gefunden. Erstelle selbstsigniertes Zertifikat...")
|
||||
generate_self_signed_cert(CERT_FILE, KEY_FILE)
|
||||
print("Selbstsigniertes SSL-Zertifikat erstellt.")
|
||||
|
||||
server_address = ('', port)
|
||||
httpd = HTTPServer(server_address, handler_class)
|
||||
|
||||
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
|
||||
context.load_cert_chain(certfile=CERT_FILE, keyfile=KEY_FILE)
|
||||
httpd.socket = context.wrap_socket(httpd.socket, server_side=True)
|
||||
return httpd
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Startfunktionen (GUI / no-GUI)
|
||||
# -------------------------------------------------------------------
|
||||
def run_server_nogui(port):
|
||||
httpd = create_https_server(port)
|
||||
server_ip = get_server_ip()
|
||||
|
||||
try:
|
||||
print(f"Starte HTTPS-Server auf https://{server_ip}:{port}")
|
||||
print("Drücke STRG+C, um zu beenden.")
|
||||
print("warte auf Verbindungen ... \n")
|
||||
print(f"Öffne im Browser: https://{server_ip}:{port}")
|
||||
print("Du musst Dich im gleichen Netzwerk befinden (Lan/ Wlan)")
|
||||
httpd.serve_forever()
|
||||
|
||||
except KeyboardInterrupt:
|
||||
# Nur eine kurze Meldung ausgeben und dann sauber herunterfahren
|
||||
print("\nSTRG+C erkannt. Fahre Server herunter...")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Fehler aufgetreten: {e}")
|
||||
logging.error("Serverfehler", exc_info=True)
|
||||
|
||||
finally:
|
||||
httpd.server_close()
|
||||
logging.shutdown()
|
||||
print("Server wurde sauber beendet.")
|
||||
|
||||
|
||||
def run_server_with_gui(port):
|
||||
# Nur für QR-Code und GUI benötigt:
|
||||
import qrcode
|
||||
import webbrowser
|
||||
from PIL import Image, ImageTk
|
||||
import tkinter as tk
|
||||
|
||||
"""Startet den Server in einem Hintergrund-Thread und öffnet eine tkinter-GUI mit QR-Code."""
|
||||
# 1) Erzeuge den Server (aber noch kein serve_forever).
|
||||
httpd = create_https_server(port)
|
||||
server_ip = get_server_ip()
|
||||
url = f"https://{server_ip}:{port}"
|
||||
|
||||
# 2) Hintergrund-Thread starten
|
||||
def server_thread():
|
||||
try:
|
||||
print(f"Starte HTTPS-Server auf {url}")
|
||||
httpd.serve_forever()
|
||||
except Exception as ex:
|
||||
print(f"Server-Thread-Exception: {ex}")
|
||||
finally:
|
||||
httpd.server_close()
|
||||
logging.shutdown()
|
||||
|
||||
t = threading.Thread(target=server_thread, daemon=True)
|
||||
t.start()
|
||||
|
||||
# 3) tkinter-GUI aufbauen
|
||||
root = tk.Tk()
|
||||
root.title("pyUpload - Secure File Upload")
|
||||
|
||||
# Favicon setzen (nur unter Windows direkt mit .ico möglich)
|
||||
try:
|
||||
root.iconbitmap("favicon.ico")
|
||||
except Exception as e:
|
||||
print(f"Konnte das Icon nicht setzen: {e}")
|
||||
|
||||
# Labels erzeugen
|
||||
labels = [
|
||||
tk.Label(root, text="HTTPS-Upload-Server läuft!", font=("Arial", 14)),
|
||||
tk.Label(root, text=f"IP-Adresse: {server_ip}", font=("Arial", 11)),
|
||||
tk.Label(root, text=f"Port: {port}", font=("Arial", 11)),
|
||||
tk.Label(root, text="Scanne den QR-Code:", font=("Arial", 11))
|
||||
]
|
||||
|
||||
# Alle Labels packen und größte Breite ermitteln
|
||||
max_width = 0
|
||||
total_height = 20 # Grundhöhe als Puffer für Abstände
|
||||
for label in labels:
|
||||
label.pack(pady=5)
|
||||
label.update_idletasks() # Breite und Höhe berechnen
|
||||
max_width = max(max_width, label.winfo_reqwidth())
|
||||
total_height += label.winfo_reqheight() + 10 # Höhe sammeln
|
||||
|
||||
# QR-Code generieren
|
||||
url = f"https://{server_ip}:{port}"
|
||||
qr = qrcode.QRCode(version=1, box_size=8, border=2)
|
||||
qr.add_data(url)
|
||||
qr.make(fit=True)
|
||||
img_qr = qr.make_image(fill_color="black", back_color="white")
|
||||
|
||||
# QR-Code als Tkinter-Image einbinden
|
||||
img_tk = ImageTk.PhotoImage(img_qr)
|
||||
label_qr = tk.Label(root, image=img_tk)
|
||||
label_qr.pack()
|
||||
total_height += img_tk.height() + 20
|
||||
|
||||
# Copyright-Vermerk
|
||||
label_copyright = tk.Label(root, text="Adam Skotarczak (C) 2025", font=("Arial", 9), fg="gray")
|
||||
label_copyright.pack(pady=5)
|
||||
total_height += label_copyright.winfo_reqheight() + 10
|
||||
|
||||
# Funktion für klickbaren Link
|
||||
def open_browser(event):
|
||||
webbrowser.open("https://www.ionivation.com/pyUpload")
|
||||
|
||||
# Klickbarer Link unter Copyright
|
||||
link_label = tk.Label(root, text="Infos: www.ionivation.com/pyUpload", font=("Arial", 10), fg="blue", cursor="hand2")
|
||||
link_label.pack()
|
||||
link_label.bind("<Button-1>", open_browser)
|
||||
total_height += link_label.winfo_reqheight() + 10
|
||||
|
||||
# Funktion zum Beenden
|
||||
def on_quit():
|
||||
root.destroy()
|
||||
|
||||
# Beenden-Button
|
||||
btn_quit = tk.Button(root, text="Beenden", command=on_quit, font=("Arial", 10))
|
||||
btn_quit.pack(pady=10)
|
||||
total_height += btn_quit.winfo_reqheight() + 20
|
||||
|
||||
# Endgültige Fenstergröße setzen
|
||||
root.geometry(f"{max_width + 40}x{total_height + 50}")
|
||||
|
||||
# 4) GUI-Loop starten
|
||||
root.mainloop()
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Hauptprogramm mit CLI
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Secure file upload server with optional GUI/QR-Code.")
|
||||
parser.add_argument("--port", "-p", type=int, default=4443, help="Port, auf dem der Server lauscht (Standard: 4443)")
|
||||
parser.add_argument("--nogui", "-n", action="store_true", help="Ohne GUI & QR-Code im reinen CLI-Modus starten")
|
||||
|
||||
args = parser.parse_args()
|
||||
print(f"Gestartet mit Port {args.port}, GUI: {not args.nogui}")
|
||||
|
||||
if args.nogui:
|
||||
run_server_nogui(args.port)
|
||||
else:
|
||||
run_server_with_gui(args.port)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
3
dev/requirements.txt
Normal file
3
dev/requirements.txt
Normal file
@ -0,0 +1,3 @@
|
||||
cryptography==44.0.2
|
||||
Pillow==11.1.0
|
||||
qrcode==8.0
|
18
dev/start.bat
Normal file
18
dev/start.bat
Normal file
@ -0,0 +1,18 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
:: Prüfen, ob die virtuelle Umgebung existiert
|
||||
if not exist venv (
|
||||
echo Virtuelle Umgebung nicht gefunden! Bitte zuerst install.bat ausführen.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
|
||||
:: Aktivieren der virtuellen Umgebung
|
||||
call venv\Scripts\activate
|
||||
|
||||
:: Starten des Upload-Servers
|
||||
python pyUpload.py
|
||||
|
||||
:: Nach Beenden der Anwendung
|
||||
deactivate
|
47
dev/success.html
Normal file
47
dev/success.html
Normal file
@ -0,0 +1,47 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="theme-color" content="#007bff">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<title>Upload Erfolgreich</title>
|
||||
<style>
|
||||
body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
background-color: #f4f4f4;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
.success-container {
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
|
||||
text-align: center;
|
||||
}
|
||||
a {
|
||||
display: inline-block;
|
||||
margin-top: 15px;
|
||||
padding: 10px 20px;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border-radius: 5px;
|
||||
}
|
||||
a:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="success-container">
|
||||
<h2>Datei erfolgreich hochgeladen!</h2>
|
||||
<p>Ihre Datei wurde erfolgreich auf den Server übertragen.</p>
|
||||
<a href="/">Neue Datei hochladen</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
93
dev/template.html
Normal file
93
dev/template.html
Normal file
@ -0,0 +1,93 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="theme-color" content="#007bff">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<title>File Upload</title>
|
||||
<style>
|
||||
body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
background-color: #f4f4f4;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
.upload-container {
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
|
||||
text-align: center;
|
||||
}
|
||||
input[type="file"] {
|
||||
display: none;
|
||||
}
|
||||
.custom-file-upload {
|
||||
display: inline-block;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
padding: 10px 20px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
}
|
||||
.custom-file-upload:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
#file-name {
|
||||
display: block;
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
color: #555;
|
||||
}
|
||||
button {
|
||||
background-color: #28a745;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
cursor: pointer;
|
||||
border-radius: 5px;
|
||||
font-size: 16px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
button:disabled {
|
||||
background-color: #cccccc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
button:hover:not(:disabled) {
|
||||
background-color: #218838;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="upload-container">
|
||||
<h2>Datei-Upload</h2>
|
||||
<form enctype="multipart/form-data" method="post" onsubmit="disableButton()">
|
||||
<label for="file-upload" class="custom-file-upload">Datei auswählen</label>
|
||||
<input id="file-upload" type="file" name="file" multiple onchange="updateFileName()">
|
||||
<span id="file-name">Keine Datei ausgewählt</span>
|
||||
<button id="upload-button" type="submit">Hochladen</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function updateFileName() {
|
||||
const input = document.getElementById("file-upload");
|
||||
const fileNameDisplay = document.getElementById("file-name");
|
||||
if (input.files.length > 0) {
|
||||
fileNameDisplay.textContent = Array.from(input.files).map(file => file.name).join(", ");
|
||||
} else {
|
||||
fileNameDisplay.textContent = "Keine Datei ausgewählt";
|
||||
}
|
||||
}
|
||||
|
||||
function disableButton() {
|
||||
document.getElementById("upload-button").disabled = true;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
10
devPyside6-test/LICENSE
Normal file
10
devPyside6-test/LICENSE
Normal file
@ -0,0 +1,10 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Adam Scotarczak (adam@skotarczak.net) - ionivation.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
93
devPyside6-test/README.md
Normal file
93
devPyside6-test/README.md
Normal file
@ -0,0 +1,93 @@
|
||||
## pyUpload - Sicherer Datei-Upload-Server für eine einfache und sichere Dateiübertragung
|
||||
|
||||
### Beschreibung
|
||||
|
||||
pyUpload ist eine leistungsstarke und dennoch einfache Lösung für den sicheren Datei-Upload über HTTPS. Es richtet sich an Privatnutzer, die eine schnelle Möglichkeit suchen, Dateien zwischen Geräten zu übertragen, sowie an Unternehmen oder Teams, die eine sichere Lösung für den internen Datenaustausch benötigen. Dieses Programm eignet sich ideal, um Dateien schnell und unkompliziert von einem Smartphone oder einem anderen Gerät auf einen Computer zu übertragen.
|
||||
|
||||
Anstatt zusätzliche Apps oder USB-Kabel zu nutzen, kann der Benutzer den Server starten, den automatisch generierten QR-Code mit dem Smartphone scannen und die Dateien direkt über die Weboberfläche hochladen. Der Computer speichert die hochgeladenen Dateien strukturiert in individuellen Verzeichnissen für jedes Gerät.
|
||||
|
||||
Zusätzlich erstellt pyUpload bei Bedarf automatisch ein selbstsigniertes SSL-Zertifikat, um eine verschlüsselte Verbindung sicherzustellen. Damit bleibt die Dateiübertragung geschützt und zuverlässig.
|
||||
|
||||
### Features – Die Vorteile von pyUpload auf einen Blick
|
||||
|
||||
- **Sichere Dateiübertragung per HTTPS** – Alle Daten werden verschlüsselt übertragen.
|
||||
- **Automatische Erstellung eines selbstsignierten SSL-Zertifikats** – Keine zusätzliche Konfiguration notwendig.
|
||||
- **Intuitive, webbasierte Benutzeroberfläche** – Einfach zu bedienen, keine Installation erforderlich.
|
||||
- **Strukturierte Speicherung** – Dateien werden in client-spezifischen Verzeichnissen gespeichert.
|
||||
- **Zentralisierte und client-spezifische Logging-Funktion** – Detaillierte Nachverfolgung aller Uploads.
|
||||
- **Flexible Nutzung mit oder ohne GUI** – Start als Desktop-Anwendung oder reine Konsolen-Version möglich.
|
||||
- **Schnelle Einrichtung** – Download, Entpacken und sofort loslegen!
|
||||
|
||||
### Installationsanleitung – So startest du pyUpload
|
||||
|
||||
Es gibt drei Möglichkeiten, pyUpload zu nutzen:
|
||||
- **Manuelle Installation** in einer vorhandenen Python-Umgebung, in der alle notwendigen Bibliotheken manuell installiert werden.
|
||||
- **Nutzung einer vorgefertigten, ausführbaren .exe (Windows) Version**, die mit pyinstaller kompiliert wurde.
|
||||
- **Nutzung in einer virtuellen Python-Umgebung**, die automatisch durch `install.bat` eingerichtet wird. Anschließend kann das Programm mit `start.bat` gestartet werden.
|
||||
|
||||
#### 1. Manuelle Installation für Python-Nutzer
|
||||
|
||||
1. Stelle sicher, dass **Python 3** auf deinem System installiert ist.
|
||||
2. Installiere alle benötigten Abhängigkeiten mit folgendem Befehl:
|
||||
```sh
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
3. Starte den Server mit:
|
||||
```sh
|
||||
python pyUpload.py
|
||||
```
|
||||
4. Falls du keine grafische Benutzeroberfläche benötigst, kannst du den Server im Konsolenmodus starten:
|
||||
```sh
|
||||
python pyUpload.py --nogui
|
||||
```
|
||||
|
||||
#### 2. Nutzung der fertigen .exe Download-Version
|
||||
|
||||
Falls du keine Python-Installation benötigst, kannst du die vorgefertigte **ZIP-Version** von pyUpload herunterladen. Diese enthält bereits alle notwendigen Dateien und ist sofort einsatzbereit.
|
||||
|
||||
1. Lade die neueste **pyUpload.zip** von der offiziellen Website herunter, inklusive virtueller Umgebung.
|
||||
2. Entpacke die ZIP-Datei in einen beliebigen Ordner.
|
||||
3. Starte die enthaltene `pyUpload.exe`.
|
||||
4. Falls die grafische Benutzeroberfläche nicht benötigt wird, kann die `pyUpload.exe` direkt in der Konsole mit `--nogui` gestartet werden:
|
||||
```sh
|
||||
pyUpload.exe --nogui
|
||||
```
|
||||
5. Eine Übersicht aller verfügbaren Befehle und Optionen erhältst du mit:
|
||||
```sh
|
||||
pyUpload.exe --help
|
||||
```
|
||||
|
||||
#### 3. Nutzung in virtueller Python-Umgebung
|
||||
|
||||
Lade die ZIP-Datei mit der virtuellen Installationsumgebung herunter und starte die `install.bat` durch Doppelklick. Es öffnet sich ein Konsolenfenster (CLI) und eine virtuelle Umgebung für pyUpload wird erstellt. Anschließend kann das Programm mit der `start.bat` gestartet werden. In der Grundeinstellung wird eine GUI mit QR-Code gestartet.
|
||||
|
||||
### Zugriff auf die Weboberfläche
|
||||
|
||||
- Sobald der Server läuft, kann er über die lokale IP-Adresse aufgerufen werden:
|
||||
```
|
||||
https://<server-ip>:4443
|
||||
```
|
||||
- Falls die GUI-Version gestartet wurde, erscheint ein **QR-Code**, der die Verbindungsadresse enthält. Dies ermöglicht eine einfache Verbindung mit Smartphones und Tablets.
|
||||
|
||||
### Datei-Upload leicht gemacht – So funktioniert es
|
||||
|
||||
1. Öffne die **Weboberfläche** im Browser.
|
||||
2. Wähle die gewünschte **Datei aus** und klicke auf **„Hochladen“**.
|
||||
3. Nach erfolgreichem Upload erscheint eine **Bestätigungsseite**, die den Abschluss der Übertragung bestätigt.
|
||||
|
||||
### SSL-Zertifikatswarnung in Browsern umgehen
|
||||
|
||||
Da pyUpload ein **selbstsigniertes SSL-Zertifikat** nutzt, wird es beim ersten Zugriff zu einer Warnung des Browsers kommen. Alternativ kann ein eigenes SSL-Zertifikat hinterlegt werden, indem die Zertifikats- und Schlüsseldateien `cert.pem` und `key.pem` durch eigene, signierte Zertifikate ersetzt werden. Um die verschlüsselte Verbindung zu akzeptieren, gibt es zwei Möglichkeiten:
|
||||
|
||||
- In den meisten Browsern gibt es eine Option wie **„Erweitert“** oder **„Trotzdem fortfahren“**, um die Warnung zu übergehen.
|
||||
- Alternativ kann das Zertifikat **manuell importiert und als vertrauenswürdig markiert** werden, um künftige Warnmeldungen zu vermeiden.
|
||||
|
||||
### Logging und Fehlerbehandlung – Transparenz und Kontrolle
|
||||
|
||||
- Alle **Uploads und Anfragen** werden in **zentralen sowie client-spezifischen Logdateien** gespeichert. Diese befinden sich im `logs/`-Verzeichnis.
|
||||
- Falls während der Nutzung von pyUpload **Probleme auftreten**, bietet ein Blick in diese Logdateien wertvolle Hinweise zur Fehlerbehebung.
|
||||
|
||||
### Lizenz und Autor
|
||||
|
||||
- **Entwickelt von Adam Skotarczak (C) 2025**.
|
||||
|
BIN
devPyside6-test/favicon.ico
Normal file
BIN
devPyside6-test/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 122 KiB |
54
devPyside6-test/install.bat
Normal file
54
devPyside6-test/install.bat
Normal file
@ -0,0 +1,54 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
:: Prüfen, ob Python installiert ist
|
||||
where python >nul 2>nul
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo Fehler: Python ist nicht installiert oder nicht im PATH!
|
||||
echo Bitte installiere Python und starte die Installation erneut.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
:: Python-Version prüfen (Mindestversion 3.8)
|
||||
for /f "tokens=2 delims= " %%v in ('python --version 2^>^&1') do set PYTHON_VERSION=%%v
|
||||
for /f "tokens=1,2 delims=." %%a in ("%PYTHON_VERSION%") do (
|
||||
if %%a LSS 3 (
|
||||
echo Fehler: Python 3.8 oder höher ist erforderlich!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
if %%a==3 if %%b LSS 8 (
|
||||
echo Fehler: Python 3.8 oder höher ist erforderlich!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
)
|
||||
|
||||
:: Virtuelle Umgebung erstellen, falls sie nicht existiert
|
||||
if not exist venv (
|
||||
echo Erstelle virtuelle Server-Umgebung ...
|
||||
python -m venv --copies venv
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo Fehler beim Erstellen der virtuellen Umgebung!
|
||||
pause
|
||||
exit /b 2
|
||||
)
|
||||
)
|
||||
|
||||
:: Aktivieren der virtuellen Umgebung
|
||||
call venv\Scripts\activate
|
||||
|
||||
:: Installieren der Abhängigkeiten
|
||||
echo Installiere Abhaengigkeiten aus dem Internet ...
|
||||
pip install --no-warn-script-location --disable-pip-version-check -r requirements.txt
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo Fehler beim Installieren der Abhaengigkeiten!
|
||||
pause
|
||||
exit /b 3
|
||||
)
|
||||
|
||||
:: Erfolgsmeldung
|
||||
echo.
|
||||
echo Installation abgeschlossen.
|
||||
timeout /t 3 >nul & exit /b 0
|
16
devPyside6-test/pyUpload.bat
Normal file
16
devPyside6-test/pyUpload.bat
Normal file
@ -0,0 +1,16 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
:: Prüfen, ob die virtuelle Umgebung existiert
|
||||
if not exist venv (
|
||||
echo Fehler: Die virtuelle Umgebung existiert nicht!
|
||||
echo Führe zuerst "install.bat" aus.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
|
||||
:: Aktivieren der virtuellen Umgebung
|
||||
call venv\Scripts\activate
|
||||
|
||||
:: Starte den Upload-Server
|
||||
python pyUpload.py
|
118
devPyside6-test/pyUpload.py
Normal file
118
devPyside6-test/pyUpload.py
Normal file
@ -0,0 +1,118 @@
|
||||
import sys
|
||||
import os
|
||||
import threading
|
||||
import socket
|
||||
import ssl
|
||||
import qrcode
|
||||
import webbrowser
|
||||
from http.server import HTTPServer, SimpleHTTPRequestHandler
|
||||
from PySide6.QtWidgets import QApplication, QLabel, QPushButton, QVBoxLayout, QWidget
|
||||
from PySide6.QtGui import QPixmap
|
||||
from PySide6.QtCore import Qt
|
||||
from PIL import ImageQt
|
||||
|
||||
|
||||
# --- HTTPS Server Klasse ---
|
||||
class SecureHTTPRequestHandler(SimpleHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
if self.path == "/":
|
||||
self.send_response(200)
|
||||
self.send_header("Content-type", "text/html")
|
||||
self.end_headers()
|
||||
self.wfile.write(b"<html><body><h1>pyUpload Server</h1><p>Upload-Seite</p></body></html>")
|
||||
else:
|
||||
self.send_error(404)
|
||||
|
||||
|
||||
def get_local_ip():
|
||||
"""Ermittelt die lokale IP-Adresse"""
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.connect(("8.8.8.8", 80))
|
||||
ip = s.getsockname()[0]
|
||||
s.close()
|
||||
return ip
|
||||
except:
|
||||
return "127.0.0.1"
|
||||
|
||||
|
||||
def run_server(port):
|
||||
"""Startet den HTTPS-Server in einem eigenen Thread"""
|
||||
server_address = ("", port)
|
||||
httpd = HTTPServer(server_address, SecureHTTPRequestHandler)
|
||||
|
||||
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
|
||||
context.load_cert_chain(certfile="cert.pem", keyfile="key.pem")
|
||||
httpd.socket = context.wrap_socket(httpd.socket, server_side=True)
|
||||
|
||||
print(f"Server läuft auf https://{get_local_ip()}:{port}")
|
||||
httpd.serve_forever()
|
||||
|
||||
|
||||
# --- PySide6 GUI ---
|
||||
class UploadGUI(QWidget):
|
||||
def __init__(self, server_ip, port):
|
||||
super().__init__()
|
||||
self.setWindowTitle("pyUpload - Secure File Upload")
|
||||
self.setGeometry(100, 100, 400, 500)
|
||||
|
||||
# Info Label
|
||||
label_info = QLabel("HTTPS-Upload-Server läuft!", self)
|
||||
label_info.setAlignment(Qt.AlignCenter)
|
||||
|
||||
label_ip = QLabel(f"IP-Adresse: {server_ip}", self)
|
||||
label_ip.setAlignment(Qt.AlignCenter)
|
||||
|
||||
label_port = QLabel(f"Port: {port}", self)
|
||||
label_port.setAlignment(Qt.AlignCenter)
|
||||
|
||||
label_hint = QLabel("Scanne den QR-Code:", self)
|
||||
label_hint.setAlignment(Qt.AlignCenter)
|
||||
|
||||
# QR-Code generieren
|
||||
url = f"https://{server_ip}:{port}"
|
||||
qr = qrcode.make(url)
|
||||
qr = qr.convert("RGB") # FIX: Konvertiere das Bild in ein gültiges Format für ImageQt
|
||||
qr_img = ImageQt.ImageQt(qr)
|
||||
pixmap = QPixmap.fromImage(qr_img)
|
||||
qr_label = QLabel(self)
|
||||
qr_label.setPixmap(pixmap)
|
||||
qr_label.setAlignment(Qt.AlignCenter)
|
||||
|
||||
|
||||
# Link Label (klickbar)
|
||||
link_label = QLabel(f'<a href="{url}">{url}</a>', self)
|
||||
link_label.setOpenExternalLinks(True)
|
||||
link_label.setAlignment(Qt.AlignCenter)
|
||||
|
||||
# Beenden Button
|
||||
btn_quit = QPushButton("Beenden", self)
|
||||
btn_quit.clicked.connect(self.close)
|
||||
|
||||
# Layout setzen
|
||||
layout = QVBoxLayout()
|
||||
layout.addWidget(label_info)
|
||||
layout.addWidget(label_ip)
|
||||
layout.addWidget(label_port)
|
||||
layout.addWidget(label_hint)
|
||||
layout.addWidget(qr_label)
|
||||
layout.addWidget(link_label)
|
||||
layout.addWidget(btn_quit)
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
|
||||
# --- Start der Anwendung ---
|
||||
if __name__ == "__main__":
|
||||
port = 4443
|
||||
server_ip = get_local_ip()
|
||||
|
||||
# HTTPS-Server in eigenem Thread starten
|
||||
server_thread = threading.Thread(target=run_server, args=(port,), daemon=True)
|
||||
server_thread.start()
|
||||
|
||||
# Qt-Anwendung starten
|
||||
app = QApplication(sys.argv)
|
||||
window = UploadGUI(server_ip, port)
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
3
devPyside6-test/requirements.txt
Normal file
3
devPyside6-test/requirements.txt
Normal file
@ -0,0 +1,3 @@
|
||||
PySide6
|
||||
qrcode
|
||||
pillow
|
18
devPyside6-test/start.bat
Normal file
18
devPyside6-test/start.bat
Normal file
@ -0,0 +1,18 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
:: Prüfen, ob die virtuelle Umgebung existiert
|
||||
if not exist venv (
|
||||
echo Virtuelle Umgebung nicht gefunden! Bitte zuerst install.bat ausführen.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
|
||||
:: Aktivieren der virtuellen Umgebung
|
||||
call venv\Scripts\activate
|
||||
|
||||
:: Starten des Upload-Servers
|
||||
python pyUpload.py
|
||||
|
||||
:: Nach Beenden der Anwendung
|
||||
deactivate
|
47
devPyside6-test/success.html
Normal file
47
devPyside6-test/success.html
Normal file
@ -0,0 +1,47 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="theme-color" content="#007bff">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<title>Upload Erfolgreich</title>
|
||||
<style>
|
||||
body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
background-color: #f4f4f4;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
.success-container {
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
|
||||
text-align: center;
|
||||
}
|
||||
a {
|
||||
display: inline-block;
|
||||
margin-top: 15px;
|
||||
padding: 10px 20px;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border-radius: 5px;
|
||||
}
|
||||
a:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="success-container">
|
||||
<h2>Datei erfolgreich hochgeladen!</h2>
|
||||
<p>Ihre Datei wurde erfolgreich auf den Server übertragen.</p>
|
||||
<a href="/">Neue Datei hochladen</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
93
devPyside6-test/template.html
Normal file
93
devPyside6-test/template.html
Normal file
@ -0,0 +1,93 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="theme-color" content="#007bff">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<title>File Upload</title>
|
||||
<style>
|
||||
body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
background-color: #f4f4f4;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
.upload-container {
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
|
||||
text-align: center;
|
||||
}
|
||||
input[type="file"] {
|
||||
display: none;
|
||||
}
|
||||
.custom-file-upload {
|
||||
display: inline-block;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
padding: 10px 20px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
}
|
||||
.custom-file-upload:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
#file-name {
|
||||
display: block;
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
color: #555;
|
||||
}
|
||||
button {
|
||||
background-color: #28a745;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
cursor: pointer;
|
||||
border-radius: 5px;
|
||||
font-size: 16px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
button:disabled {
|
||||
background-color: #cccccc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
button:hover:not(:disabled) {
|
||||
background-color: #218838;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="upload-container">
|
||||
<h2>Datei-Upload</h2>
|
||||
<form enctype="multipart/form-data" method="post" onsubmit="disableButton()">
|
||||
<label for="file-upload" class="custom-file-upload">Datei auswählen</label>
|
||||
<input id="file-upload" type="file" name="file" multiple onchange="updateFileName()">
|
||||
<span id="file-name">Keine Datei ausgewählt</span>
|
||||
<button id="upload-button" type="submit">Hochladen</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function updateFileName() {
|
||||
const input = document.getElementById("file-upload");
|
||||
const fileNameDisplay = document.getElementById("file-name");
|
||||
if (input.files.length > 0) {
|
||||
fileNameDisplay.textContent = Array.from(input.files).map(file => file.name).join(", ");
|
||||
} else {
|
||||
fileNameDisplay.textContent = "Keine Datei ausgewählt";
|
||||
}
|
||||
}
|
||||
|
||||
function disableButton() {
|
||||
document.getElementById("upload-button").disabled = true;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
93
info.md
Normal file
93
info.md
Normal file
@ -0,0 +1,93 @@
|
||||
## pyUpload - Sicherer Datei-Upload-Server für eine einfache und sichere Dateiübertragung
|
||||
|
||||
### Beschreibung
|
||||
|
||||
pyUpload ist eine leistungsstarke und dennoch einfache Lösung für den sicheren Datei-Upload über HTTPS. Dieses Programm eignet sich ideal, um Dateien schnell und unkompliziert von einem Smartphone oder einem anderen Gerät auf einen Computer zu übertragen.
|
||||
|
||||
Anstatt zusätzliche Apps oder USB-Kabel zu nutzen, kann der Benutzer den Server starten, den automatisch generierten QR-Code mit dem Smartphone scannen und die Dateien direkt über die Weboberfläche hochladen. Der Computer speichert die hochgeladenen Dateien strukturiert in individuellen Verzeichnissen für jedes Gerät.
|
||||
|
||||
Zusätzlich erstellt pyUpload bei Bedarf automatisch ein selbstsigniertes SSL-Zertifikat, um eine verschlüsselte Verbindung sicherzustellen. Damit bleibt die Dateiübertragung geschützt und zuverlässig.
|
||||
|
||||
### Download
|
||||
- **Portabel für Windows als .zip**
|
||||
[download id="2323"]
|
||||
|
||||
> Aktuell ist der Download der portablen und Compilierten Version gesperrt da es von diversen Virenscannern als Bedrohung eingestuft wird. Bei Interesse ist das Programm aktuell nur auf Anfrage per eMail erhältlich. In Kürze erfolgt eine Veröffentlichung inklusive Code auf GitHub.
|
||||
|
||||
|
||||
### Features – Die Vorteile von pyUpload auf einen Blick
|
||||
|
||||
- **Sichere Dateiübertragung per HTTPS** – Alle Daten werden verschlüsselt übertragen.
|
||||
- **Automatische Erstellung eines selbstsignierten SSL-Zertifikats** – Keine zusätzliche Konfiguration notwendig.
|
||||
- **Intuitive, webbasierte Benutzeroberfläche** – Einfach zu bedienen, keine Installation erforderlich.
|
||||
- **Strukturierte Speicherung** – Dateien werden in client-spezifischen Verzeichnissen gespeichert.
|
||||
- **Zentralisierte und client-spezifische Logging-Funktion** – Detaillierte Nachverfolgung aller Uploads.
|
||||
- **Flexible Nutzung mit oder ohne GUI** – Start als Desktop-Anwendung oder reine Konsolen-Version möglich.
|
||||
- **Schnelle Einrichtung** – Download, Entpacken und sofort loslegen!
|
||||
|
||||
### Installationsanleitung – So startest du pyUpload
|
||||
|
||||
Es gibt zwei Möglichkeiten, pyUpload zu nutzen: Entweder die manuelle Installation oder die Nutzung einer vorgefertigten, ausführbaren Version.
|
||||
|
||||
#### 1. Nutzung der fertigen Download-Version
|
||||
|
||||
Falls du keine Python-Installation benötigst, kannst du die vorgefertigte **ZIP-Version** von pyUpload herunterladen. Diese enthält bereits alle notwendigen Dateien und ist sofort einsatzbereit.
|
||||
|
||||
1. Lade die neueste **pyUpload.zip** von der offiziellen Website herunter.
|
||||
2. Entpacke die ZIP-Datei in einen beliebigen Ordner.
|
||||
3. Starte die enthaltene `pyUpload.exe`.
|
||||
4. Falls die grafische Benutzeroberfläche nicht benötigt wird, kann die `pyUpload.exe` direkt in der Konsole mit `--nogui` gestartet werden:
|
||||
```sh
|
||||
pyUpload.exe --nogui
|
||||
```
|
||||
5. Eine Übersicht aller verfügbaren Befehle und Optionen erhältst du mit:
|
||||
```sh
|
||||
pyUpload.exe --help
|
||||
```
|
||||
|
||||
#### 2. Manuelle Installation für Python-Nutzer
|
||||
|
||||
1. Stelle sicher, dass **Python 3** auf deinem System installiert ist.
|
||||
2. Installiere alle benötigten Abhängigkeiten mit folgendem Befehl:
|
||||
```sh
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
3. Starte den Server mit:
|
||||
```sh
|
||||
python pyUpload.py
|
||||
```
|
||||
4. Falls du keine grafische Benutzeroberfläche benötigst, kannst du den Server im Konsolenmodus starten:
|
||||
```sh
|
||||
python pyUpload.py --nogui
|
||||
```
|
||||
|
||||
### Zugriff auf die Weboberfläche
|
||||
|
||||
- Sobald der Server läuft, kann er über die lokale IP-Adresse aufgerufen werden:
|
||||
```
|
||||
https://<server-ip>:4443
|
||||
```
|
||||
- Falls die GUI-Version gestartet wurde, erscheint ein **QR-Code**, der die Verbindungsadresse enthält. Dies ermöglicht eine einfache Verbindung mit Smartphones und Tablets.
|
||||
|
||||
### Datei-Upload leicht gemacht – So funktioniert es
|
||||
|
||||
1. Öffne die **Weboberfläche** im Browser.
|
||||
2. Wähle die gewünschte **Datei aus** und klicke auf **„Hochladen“**.
|
||||
3. Nach erfolgreichem Upload erscheint eine **Bestätigungsseite**, die den Abschluss der Übertragung bestätigt.
|
||||
|
||||
### SSL-Zertifikatswarnung in Browsern umgehen
|
||||
|
||||
Da pyUpload ein **selbstsigniertes SSL-Zertifikat** nutzt, kann es beim ersten Zugriff zu einer Warnung des Browsers kommen. Um die verschlüsselte Verbindung zu akzeptieren, gibt es zwei Möglichkeiten:
|
||||
|
||||
- In den meisten Browsern gibt es eine Option wie **„Erweitert“** oder **„Trotzdem fortfahren“**, um die Warnung zu übergehen.
|
||||
- Alternativ kann das Zertifikat **manuell importiert und als vertrauenswürdig markiert** werden, um künftige Warnmeldungen zu vermeiden.
|
||||
|
||||
### Logging und Fehlerbehandlung – Transparenz und Kontrolle
|
||||
|
||||
- Alle **Uploads und Anfragen** werden in **zentralen sowie client-spezifischen Logdateien** gespeichert. Diese befinden sich im `logs/`-Verzeichnis.
|
||||
- Falls während der Nutzung von pyUpload **Probleme auftreten**, bietet ein Blick in diese Logdateien wertvolle Hinweise zur Fehlerbehebung.
|
||||
|
||||
### Lizenz und Autor
|
||||
|
||||
- **Entwickelt von Adam Skotarczak (C) 2025**.
|
||||
|
84
innoSetup.iss
Normal file
84
innoSetup.iss
Normal file
@ -0,0 +1,84 @@
|
||||
; Define AppVersion as a constant
|
||||
#define AppVersion "0.1.0"
|
||||
#define BasePath ".\dev"
|
||||
|
||||
; Source: "{#BasePath}\*"; DestDir: "{app}"; Flags: ignoreversion;
|
||||
|
||||
|
||||
[Setup]
|
||||
AppId={{832B3E5D-14BC-4823-A911-00C9B79AD040}
|
||||
AppName=pyUpload
|
||||
AppVersion={#AppVersion}
|
||||
AppVerName=pyUpload {#AppVersion} (win)
|
||||
AppPublisher=Adam Skotarczak (ionivation.com)
|
||||
AppPublisherURL=https://www.ionivation.com/pyupload/
|
||||
AppSupportURL=https://www.ionivation.com/pyupload/
|
||||
AppUpdatesURL=https://www.ionivation.com/pyupload/
|
||||
DefaultDirName={userappdata}\pyUpload
|
||||
DisableProgramGroupPage=yes
|
||||
LicenseFile={#BasePath}\LICENSE
|
||||
PrivilegesRequired=lowest
|
||||
;PrivilegesRequiredOverridesAllowed=dialog
|
||||
OutputBaseFilename=pyUpload-Setup-{#AppVersion}
|
||||
SolidCompression=yes
|
||||
WizardStyle=modern
|
||||
SetupIconFile={#BasePath}\favicon.ico
|
||||
DisableDirPage=yes
|
||||
|
||||
[Languages]
|
||||
Name: "german"; MessagesFile: "compiler:Languages\German.isl"
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
|
||||
[Files]
|
||||
Source: "{#BasePath}\pyUpload.bat"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "{#BasePath}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
|
||||
[Dirs]
|
||||
Name: "{app}\upload"; Flags: uninsalwaysuninstall
|
||||
|
||||
[Icons]
|
||||
Name: "{autoprograms}\pyUpload"; Filename: "{app}\pyUpload.bat"; IconFilename: "{app}\favicon.ico";
|
||||
Name: "{autodesktop}\pyUpload"; Filename: "{app}\pyUpload.bat"; IconFilename: "{app}\favicon.ico"; Tasks: desktopicon
|
||||
Name: "{userdesktop}\pyUpload-Uploads"; Filename: "{app}\upload"; IconFilename: "{app}\favicon.ico"; Tasks: desktopicon
|
||||
|
||||
|
||||
[Tasks]
|
||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
|
||||
|
||||
[Run]
|
||||
Filename: "{app}\install.bat"; Parameters: ""; WorkingDir: "{app}\"; Flags: waituntilterminated
|
||||
;Flags: runhidden
|
||||
|
||||
Filename: "{app}\pyUpload.bat"; Description: "{cm:LaunchProgram,pyUpload}"; Flags: shellexec postinstall skipifsilent
|
||||
|
||||
[Code]
|
||||
function IsPythonInstalled(): Boolean;
|
||||
var
|
||||
PythonPath: String;
|
||||
ResultCode: Integer;
|
||||
begin
|
||||
// Prüfe Registry für alle möglichen Python-Versionen (dynamisch)
|
||||
if RegQueryStringValue(HKLM, 'SOFTWARE\Python\PythonCore', '', PythonPath) or
|
||||
RegQueryStringValue(HKLM, 'SOFTWARE\WOW6432Node\Python\PythonCore', '', PythonPath) then
|
||||
begin
|
||||
Result := True;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
// Prüfe mit python --version, falls kein Registry-Eintrag gefunden wurde
|
||||
Result := Exec('cmd.exe', '/c python --version', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
|
||||
end;
|
||||
|
||||
function InitializeSetup(): Boolean;
|
||||
begin
|
||||
if not IsPythonInstalled() then
|
||||
begin
|
||||
MsgBox('Python ist nicht installiert oder nicht erreichbar! Bitte installiere Python.', mbError, MB_OK);
|
||||
Result := False; // Installation abbrechen
|
||||
end
|
||||
else
|
||||
begin
|
||||
Result := True;
|
||||
end;
|
||||
end;
|
||||
|
Loading…
x
Reference in New Issue
Block a user