ApoAlly Insights Einrichtung#
Windows Server 2019#
Powershell Upload-Script
apoally-insights-upload.ps1
# upload_csv.ps1
#
# This script now automatically searches for an optional schema file (.json or .csvs)
# with the same base name as the CSV/TSV file. JSON has priority over CSVS if both exist.
# If no schema file is found, only the CSV/TSV will be uploaded.
#
# Environment:
# $apiUrl - Default: "https://api.apoally.de/insights/upload"
# $apiKey - Default: "YOUR-API-KEY"
# $csvFolder - Default: "D:\ApoAlly-Insights"
# $waitMinutes - Default: 5
#
# This script checks each CSV/TSV file in the $csvFolder. If a file is older than $waitMinutes,
# it will be uploaded to the API. If an error occurs, an error.log is created.
# Configuration
$apiUrl = "https://api.apoally.de/insights/upload"
$apiKey = "YOUR-API-KEY"
$csvFolder = "D:\ApoAlly-Insights"
$waitMinutes = 5
function Upload-SingleFile {
param (
[string]$CsvFile
)
# Check for an existing JSON or CSVS schema file with the same base name (JSON has priority)
$schemaFileJson = Join-Path $CsvFile.DirectoryName ("$($CsvFile.BaseName).json")
$schemaFileCsvs = Join-Path $CsvFile.DirectoryName ("$($CsvFile.BaseName).csvs")
$schemaFileToUpload = $null
if (Test-Path $schemaFileJson) {
$schemaFileToUpload = $schemaFileJson
}
elseif (Test-Path $schemaFileCsvs) {
$schemaFileToUpload = $schemaFileCsvs
}
Write-Host "Uploading file: $($CsvFile.FullName)"
if ($schemaFileToUpload) {
Write-Host "Found optional schema file: $schemaFileToUpload"
}
# Determine MIME type based on extension (.csv or .tsv)
$extension = $CsvFile.Extension.ToLower()
$contentType = "text/csv"
if ($extension -eq ".tsv") {
$contentType = "text/tab-separated-values"
}
# Build the multipart/form-data body
$boundary = "----MyBoundary$(Get-Random)"
$LF = "`r`n"
$bodyLines = @()
# 1) Add the CSV/TSV part
$csvContent = Get-Content $CsvFile.FullName -Raw
$bodyLines += "--$boundary"
$bodyLines += "Content-Disposition: form-data; name=`"files`"; filename=`"$($CsvFile.Name)`""
$bodyLines += "Content-Type: $contentType$LF"
$bodyLines += $csvContent
# 2) If we have a schema file, add it as a second part
if ($schemaFileToUpload) {
$schemaContent = Get-Content $schemaFileToUpload -Raw
$bodyLines += "--$boundary"
$bodyLines += "Content-Disposition: form-data; name=`"files`"; filename=`"$($schemaFileToUpload)`""
if ($schemaFileToUpload.ToLower().EndsWith(".json")) {
$bodyLines += "Content-Type: application/json$LF"
}
else {
# For .csvs, we can treat it as text
$bodyLines += "Content-Type: text/plain$LF"
}
$bodyLines += $schemaContent
}
# End boundary
$bodyLines += "--$boundary--"
$body = $bodyLines -join $LF
$headers = @{
"X-API-Key" = $apiKey
"Content-Type" = "multipart/form-data; boundary=$boundary"
}
try {
$response = Invoke-RestMethod -Uri $apiUrl -Method Post -Headers $headers -Body $body
return $response
}
catch {
throw $_
}
}
function Upload-CSVFiles {
param (
[string]$Folder
)
# Get all CSV and TSV files recursively, ignoring those matching '_img.csv' or '_img.tsv'
$csvFiles = Get-ChildItem -Path $Folder -Recurse -File -Include *.csv, *.tsv |
Where-Object { $_.Name -notmatch '_img\.(csv|tsv)$' }
foreach ($file in $csvFiles) {
# Define the error log file name for the data file
$errorLog = Join-Path $file.DirectoryName ("$($file.BaseName).error.log")
# Skip if an error log already exists
if (Test-Path $errorLog) {
Write-Host "Skipping file due to existing error log: $($file.FullName)"
continue
}
# Check if the file is at least $waitMinutes old
$fileAge = (Get-Date) - $file.LastWriteTime
if ($fileAge.TotalMinutes -lt $waitMinutes) {
Write-Host "File is not old enough (Age: $([math]::Round($fileAge.TotalMinutes, 2)) minutes): $($file.FullName)"
continue
}
Write-Host "Attempting upload of: $($file.FullName)"
try {
$response = Upload-SingleFile -CsvFile $file
if ($response.status -eq "success") {
Write-Host "Upload successful: $($file.FullName)"
Remove-Item $file.FullName -Force
# Check and delete any associated _img.csv or _img.tsv file
$imgCsv = Join-Path $file.DirectoryName ("$($file.BaseName)_img.csv")
$imgTsv = Join-Path $file.DirectoryName ("$($file.BaseName)_img.tsv")
if (Test-Path $imgCsv) {
Remove-Item $imgCsv -Force
Write-Host "Deleted associated _img.csv file: $imgCsv"
}
if (Test-Path $imgTsv) {
Remove-Item $imgTsv -Force
Write-Host "Deleted associated _img.tsv file: $imgTsv"
}
}
else {
Write-Host "Upload failed for file: $($file.FullName). Creating error log."
$errorMessage = "Error uploading: " + ($response.error)
$errorMessage | Out-File -FilePath $errorLog -Encoding utf8
}
}
catch {
Write-Host "Error uploading file $($file.FullName): $_. Creating error log."
$_ | Out-File -FilePath $errorLog -Encoding utf8
}
}
}
function Start-Watch {
param (
[string]$Folder,
[int]$WaitMinutes
)
# Initial processing at startup
Upload-CSVFiles -Folder $Folder
# Endlessly repeat, waiting 1 minute between checks
while ($true) {
Start-Sleep -Seconds 60
Upload-CSVFiles -Folder $Folder
}
}
# Start folder watch
Start-Watch -Folder $csvFolder -WaitMinutes $waitMinutes
Anleitung zur Installation und Konfiguration des Scripts#
1. Script speichern#
- Öffnen Sie den Editor (z. B. Notepad).
- Kopieren Sie den Inhalt des PowerShell-Scripts
apoally-insights-upload.ps1in den Editor. - Speichern Sie die Datei unter dem Namen
apoally-insights-upload.ps1im gewünschten Verzeichnis, z. B.C:\Scripts.
2. PowerShell-Ausführungsrichtlinie anpassen#
Um das Script auszuführen, muss die PowerShell-Ausführungsrichtlinie angepasst werden:
- Öffnen Sie PowerShell als Administrator.
- Geben Sie den folgenden Befehl ein, um die Ausführungsrichtlinie zu ändern:
- Bestätigen Sie die Änderung mit
Y(Ja).
3. API-Key und Konfiguration anpassen#
- Öffnen Sie die Datei
apoally-insights-upload.ps1mit einem Texteditor. - Ersetzen Sie
YOUR-API-KEYdurch Ihren tatsächlichen API-Schlüssel. - Passen Sie den Pfad für den Ordner
$csvFolderan, falls Ihre CSV-Dateien in einem anderen Verzeichnis gespeichert sind. - Speichern Sie die Änderungen.
4. Task für Autostart einrichten#
Um das Script automatisch beim Systemstart auszuführen, richten Sie einen geplanten Task ein:
- Öffnen Sie den Task Scheduler (Aufgabenplanung) über das Startmenü.
- Klicken Sie auf Task erstellen.
- Geben Sie unter Allgemein einen Namen für den Task ein, z. B.
ApoAlly Insights Upload. - Aktivieren Sie die Option Mit höchsten Privilegien ausführen.
- Wechseln Sie zum Tab Trigger und klicken Sie auf Neu: - Wählen Sie Beim Start aus. - Klicken Sie auf OK.
- Wechseln Sie zum Tab Aktionen und klicken Sie auf Neu: - Wählen Sie Programm starten aus. - Geben Sie folgendes in das Feld Programm/Skript ein: - Geben Sie folgendes in das Feld Argumente hinzufügen (optional) ein: - Klicken Sie auf OK.
- Wechseln Sie zum Tab Bedingungen und deaktivieren Sie die Option Task nur starten, wenn der Computer im Netzbetrieb ausgeführt wird, falls der Task auch im Akkubetrieb ausgeführt werden soll.
- Klicken Sie auf OK, um den Task zu erstellen.
5. Testlauf#
- Führen Sie das Script manuell aus, um sicherzustellen, dass es korrekt funktioniert:
- Überprüfen Sie die Ausgabe und die erstellten Logdateien, um sicherzustellen, dass keine Fehler auftreten.
6. Überwachung und Fehlerbehebung#
- Überprüfen Sie regelmäßig die Logdateien, die im gleichen Verzeichnis wie die CSV-Dateien gespeichert werden.
- Falls der geplante Task nicht ausgeführt wird, überprüfen Sie die Einstellungen im Task Scheduler und stellen Sie sicher, dass das Script korrekt konfiguriert ist.
Mit diesen Schritten ist das Script erfolgreich auf Ihrem Windows Server 2019 eingerichtet und wird automatisch beim Start des Systems ausgeführt.