PowerShell Skript Beispiel (.ps1)
# =======================
# BEARING X Upload mit Login, Fortschrittsbalken & klaren Fehlermeldungen
# Kompatibel: Windows PowerShell 5.1
# =======================
# --- KONFIG ---
$PROTOCOL = "https"
$BASE_URL = "example.app.bearingx.io" # ohne https://
$USERNAME = "exampleUserBEARINGX"
$PASSWORD = "examplePasswordBEARINGX"
$FILENAME = "C:\Users\DeniseHaddad\Desktop\BX Upload\BEARING X - CSV-Testliste-kurz.csv"
$WORKDIR = ".\"
# --- VORBEREITUNG ---
$ProgressPreference = 'Continue'
$GLOBAL:BX_PROGRESS_ID = 1
# Basis-URI als Uri-Objekt (wichtig für Cookies)
$BASE_URI = [uri]("{0}://{1}" -f $PROTOCOL, $BASE_URL)
# --- HILFSFUNKTIONEN ---
function Show-ErrorSpecific {
param(
[Parameter(Mandatory)]$Exception,
[string]$Context = ""
)
Write-Host ""
Write-Host "❌ $Context" -ForegroundColor Red
if ($Exception -is [System.Net.WebException]) {
$webEx = [System.Net.WebException]$Exception
try {
$resp = [System.Net.HttpWebResponse]$webEx.Response
if ($resp) {
$code = [int]$resp.StatusCode
Write-Host ("HTTP {0} {1}" -f $code, $resp.StatusDescription) -ForegroundColor Yellow
if ($code -eq 401) { Write-Host "Unauthorized – Benutzername/Passwort falsch." -ForegroundColor Yellow }
elseif ($code -eq 403) { Write-Host "Forbidden – Zugriff verweigert." -ForegroundColor Yellow }
try {
$reader = New-Object System.IO.StreamReader($resp.GetResponseStream())
$body = $reader.ReadToEnd()
if ($body) {
Write-Host "--- Serverantwort ---" -ForegroundColor DarkGray
Write-Host $body
Write-Host "---------------------" -ForegroundColor DarkGray
}
} catch {}
} else {
switch ($webEx.Status) {
'NameResolutionFailure' { Write-Host "DNS-Auflösung fehlgeschlagen. Prüfe BASE_URL: $($BASE_URI.Host)" -ForegroundColor Yellow }
'ConnectFailure' { Write-Host "Verbindung fehlgeschlagen. Firewall/Proxy/URL prüfen." -ForegroundColor Yellow }
'Timeout' { Write-Host "Zeitüberschreitung. Server reagiert nicht." -ForegroundColor Yellow }
default { Write-Host "Netzwerkfehler: $($webEx.Status)" -ForegroundColor Yellow }
}
}
} catch {
Write-Host "Fehler beim Auslesen der HTTP-Antwort." -ForegroundColor Yellow
}
} else {
Write-Host ($Exception.Message) -ForegroundColor Yellow
}
}
function Fail {
param([string]$Message = "Fehler beim Upload.")
Write-Host $Message -ForegroundColor Red
Write-Progress -Id $GLOBAL:BX_PROGRESS_ID -Activity "Upload" -Completed
exit 1
}
# Auth-Check gegen eine gesicherte API (liefert 2xx nur mit gültiger Session)
function Test-AuthenticatedSession {
param(
[Parameter(Mandatory)][uri]$BaseUri,
[Parameter(Mandatory)][Microsoft.PowerShell.Commands.WebRequestSession]$WebSession
)
$testUri = [uri]("$($BaseUri.Scheme)://$($BaseUri.Host)/api/trades?page=0&size=1")
try {
$r = Invoke-WebRequest -Uri $testUri -WebSession $WebSession -Method GET -ErrorAction Stop
return ($r.StatusCode -ge 200 -and $r.StatusCode -lt 300)
} catch {
if ($_.Exception -is [System.Net.WebException]) {
try {
$resp = [System.Net.HttpWebResponse]$_.Exception.Response
if ($resp) {
$code = [int]$resp.StatusCode
if ($code -in 401,403) { return $false }
}
} catch {}
}
throw # andere Fehler nach oben geben
}
}
# Upload als Stream mit Fortschritt
function Invoke-MultipartUploadWithProgress {
param(
[Parameter(Mandatory)] [string] $Uri,
[Parameter(Mandatory)] [string] $FilePath,
[Parameter(Mandatory)] [Microsoft.PowerShell.Commands.WebRequestSession] $WebSession
)
if (-not (Test-Path -LiteralPath $FilePath)) { Fail "CSV-Datei nicht gefunden: $FilePath" }
$fileInfo = Get-Item -LiteralPath $FilePath
if ($fileInfo.Length -le 0) { Fail "CSV-Datei ist leer: $FilePath" }
$boundary = "----BXBoundary$([System.Guid]::NewGuid().ToString('N'))"
$fileName = $fileInfo.Name
$pre = "--$boundary`r`n" +
"Content-Disposition: form-data; name=`"file`"; filename=`"$fileName`"`r`n" +
"Content-Type: text/csv`r`n`r`n"
$post = "`r`n--$boundary--`r`n"
$preBytes = [System.Text.Encoding]::UTF8.GetBytes($pre)
$postBytes = [System.Text.Encoding]::UTF8.GetBytes($post)
$totalLen = $preBytes.Length + $fileInfo.Length + $postBytes.Length
$req = [System.Net.HttpWebRequest]::Create($Uri)
$req.Method = "POST"
$req.ContentType = "multipart/form-data; boundary=$boundary"
$req.CookieContainer = $WebSession.Cookies
$req.AllowWriteStreamBuffering = $false
$req.SendChunked = $false
$req.ContentLength = $totalLen
$req.Timeout = 1000 * 60 * 10
$req.UserAgent = "PowerShell-Upload/1.0"
$req.Accept = "application/json, */*"
$req.Headers.Add("X-Requested-With","XMLHttpRequest")
$bufferSize = 64KB
$bytesSent = 0
try {
$requestStream = $req.GetRequestStream()
# Header
$requestStream.Write($preBytes, 0, $preBytes.Length)
$bytesSent += $preBytes.Length
$pct = [math]::Round(($bytesSent / $totalLen) * 100)
Write-Progress -Id $GLOBAL:BX_PROGRESS_ID -Activity "Upload vorbereiten" -Status "Header senden..." -PercentComplete $pct
# Datei
$fs = [System.IO.File]::OpenRead($FilePath)
try {
$buffer = New-Object byte[] $bufferSize
while (($read = $fs.Read($buffer, 0, $buffer.Length)) -gt 0) {
$requestStream.Write($buffer, 0, $read)
$bytesSent += $read
$pct = [math]::Round(($bytesSent / $totalLen) * 100)
$mbSent = [math]::Round($bytesSent / 1MB, 2)
$mbTotal = [math]::Round($totalLen / 1MB, 2)
Write-Progress -Id $GLOBAL:BX_PROGRESS_ID -Activity "Upload läuft" -Status "$mbSent / $mbTotal MB übertragen..." -PercentComplete $pct
}
} finally {
$fs.Close()
}
# Trailer
$requestStream.Write($postBytes, 0, $postBytes.Length)
Write-Progress -Id $GLOBAL:BX_PROGRESS_ID -Activity "Upload abschließen" -Status "Finalisieren..." -PercentComplete 100
$requestStream.Flush()
$requestStream.Close()
# Antwort
$resp = [System.Net.HttpWebResponse]$req.GetResponse()
try {
Write-Progress -Id $GLOBAL:BX_PROGRESS_ID -Activity "Upload" -Completed
Write-Host ("✅ Upload erfolgreich! HTTP {0} {1}" -f [int]$resp.StatusCode, $resp.StatusDescription) -ForegroundColor Green
} finally {
$resp.Close()
}
} catch {
Write-Progress -Id $GLOBAL:BX_PROGRESS_ID -Activity "Upload" -Completed
Show-ErrorSpecific -Exception $_.Exception -Context "Upload fehlgeschlagen."
exit 1
}
}
# --- START ---
Write-Host "Starting automatic upload..." -ForegroundColor Cyan
# TLS
try {
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls13
} catch {
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
}
# Arbeitsverzeichnis
try {
Set-Location -Path $WORKDIR -ErrorAction Stop
} catch {
Show-ErrorSpecific -Exception $_.Exception -Context "Arbeitsverzeichnis konnte nicht gesetzt werden: $WORKDIR"
exit 1
}
# Checks
if ([string]::IsNullOrWhiteSpace($BASE_URL)) { Fail "BASE_URL fehlt." }
if ($BASE_URL -match "^https?://") { Fail "BASE_URL bitte ohne Protokoll angeben (z. B. 'earlybrands.app.bearingx.io')." }
if (-not (Test-Path -LiteralPath $FILENAME)) { Fail "CSV-Datei nicht gefunden: $FILENAME" }
# Login
$loginUri = [uri]("$($BASE_URI.Scheme)://$($BASE_URI.Host)/login")
Write-Host "Logging in as '$USERNAME'..." -ForegroundColor Cyan
$Session = New-Object Microsoft.PowerShell.Commands.WebRequestSession
try {
$loginResponse = Invoke-WebRequest -Uri $loginUri `
-Method POST `
-Body @{ username = $USERNAME; password = $PASSWORD } `
-ContentType "application/x-www-form-urlencoded" `
-WebSession $Session `
-ErrorAction Stop
# Falls wir noch auf /login hängen oder die Seite das Login-Formular zeigt => sehr wahrscheinlich Fehl-Login.
$onLoginPage = $loginResponse.BaseResponse.ResponseUri.AbsolutePath -match '/login'
$showsFormAgain = $false
try { if ($loginResponse.Content -match 'name="username"') { $showsFormAgain = $true } } catch {}
# Harter Auth-Check gegen API
$authOK = $false
if (-not $onLoginPage -and -not $showsFormAgain) {
$authOK = Test-AuthenticatedSession -BaseUri $BASE_URI -WebSession $Session
}
if ($authOK) {
Write-Host "✅ Login erfolgreich." -ForegroundColor Green
} else {
Fail "Login fehlgeschlagen – Benutzername/Passwort falsch oder keine gültige Session."
}
} catch {
Show-ErrorSpecific -Exception $_.Exception -Context "Login fehlgeschlagen."
exit 1
}
# Upload
$uploadUri = "$($BASE_URI.Scheme)://$($BASE_URI.Host)/api/orders/upload"
Write-Host "Starte Upload: '$FILENAME'" -ForegroundColor Cyan
Invoke-MultipartUploadWithProgress -Uri $uploadUri -FilePath $FILENAME -WebSession $Session
Write-Host "Process completed." -ForegroundColor Cyan
exit 0
Wie funktioniert das Skript?
Die folgende Beschreibung basiert auf dem oben dargestellte Skript. Das Skript ist nur ein Beispiel dafür, wie ein Upload möglich ist.
Um das Skript auszuführen, muss PowerShell ISE als Administrator geöffnet werden (am besten in die Windows Suche eingeben und dann mit rechtsklick als Administrator öffnen). Dann das oben dargestellte Skript einfügen. Die Zeilen mit der URL, dem Usernamen, dem Passwort und dem Dateipfad müssen angepasst werden (lila farbende Zeilen). Zum Schluss nur noch das Skript ausführen (grüner Play-Button).
Bei erfolgreichem Upload, gibt das Skript eine positive Rückmeldung.