Added new features for ImgBB_Upload ps script

This commit is contained in:
iminet
2026-10-22 09:42:00 +02:00
parent dd871418fc
commit c00483fac8
2 changed files with 93 additions and 20 deletions
+58 -11
View File
@@ -13,12 +13,18 @@
retries/skips, and red for errors. Text labels remain readable without color. retries/skips, and red for errors. Text labels remain readable without color.
.PARAMETER DirectoryPath .PARAMETER DirectoryPath
An existing directory. Treated as a literal path, including brackets. An existing directory. Treated as a literal path, including brackets.
Required unless FilePath is supplied. Ignored when FilePath is supplied.
.PARAMETER FilePath
One existing JPG, JPEG, or PNG file, interpreted literally. Takes precedence
over DirectoryPath. An invalid FilePath fails without falling back to a
directory scan. Recurse has no effect in single-file mode.
.PARAMETER ApiKey .PARAMETER ApiKey
ImgBB API key. A nonblank value overrides IMGBB_API_KEY. Prefer the environment ImgBB API key. A nonblank value overrides IMGBB_API_KEY. Prefer the environment
variable to avoid saving a key in shell history. The key is sent in the POST variable to avoid saving a key in shell history. The key is sent in the POST
body, never in the URL or script-generated messages. body, never in the URL or script-generated messages.
.PARAMETER Recurse .PARAMETER Recurse
Include subdirectories. Disabled by default. Hidden files are not included. Include subdirectories. Disabled by default. Hidden files are not included.
Ignored when FilePath is supplied.
.PARAMETER WaitTime .PARAMETER WaitTime
Random (default) enables a random 3-6 second pause between requests. Random (default) enables a random 3-6 second pause between requests.
Only Off disables this ordinary pause. Omitted, empty, or unrecognized Only Off disables this ordinary pause. Omitted, empty, or unrecognized
@@ -43,6 +49,11 @@
.EXAMPLE .EXAMPLE
.\Upload-ImagesToImgBB.ps1 -DirectoryPath './images' -WaitTime Off .\Upload-ImagesToImgBB.ps1 -DirectoryPath './images' -WaitTime Off
Disables ordinary request delays while retaining retry waits. Disables ordinary request delays while retaining retry waits.
.EXAMPLE
.\Upload-ImagesToImgBB.ps1 -FilePath 'C:\Images\photo.jpg' -DryRun
.EXAMPLE
.\Upload-ImagesToImgBB.ps1 -FilePath 'C:\Images\photo.jpg' -DirectoryPath 'C:\OtherImages'
Uploads only photo.jpg; DirectoryPath is ignored.
.NOTES .NOTES
Intended for Windows PowerShell 5.1 and PowerShell 7. Intended for Windows PowerShell 5.1 and PowerShell 7.
Exit codes: 0 = success (including no matching files); 1 = any failure. Exit codes: 0 = success (including no matching files); 1 = any failure.
@@ -78,10 +89,8 @@
[CmdletBinding()] [CmdletBinding()]
param ( param (
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]$DirectoryPath, [string]$DirectoryPath,
[string]$FilePath,
[string]$ApiKey, [string]$ApiKey,
[AllowNull()] [AllowNull()]
[AllowEmptyString()] [AllowEmptyString()]
@@ -170,6 +179,37 @@ if ([string]::IsNullOrWhiteSpace($finalApiKey)) {
exit 1 exit 1
} }
# Presence, rather than validity, determines precedence. Never silently upload
# a directory when the caller explicitly selected a missing or invalid file.
$useFilePath = $PSBoundParameters.ContainsKey('FilePath')
$supportedExtensions = @('.jpg', '.jpeg', '.png')
$inputError = if ($useFilePath) {
'FilePath must identify an existing, accessible JPG, JPEG, or PNG file. DirectoryPath is ignored.'
}
else { 'DirectoryPath must identify an existing, accessible filesystem directory, or supply -FilePath.' }
try {
if ($useFilePath) {
if ([string]::IsNullOrWhiteSpace($FilePath)) { throw 'Empty file path.' }
$selectedFile = Get-Item -LiteralPath $FilePath -ErrorAction Stop
if ($selectedFile.PSIsContainer -or $selectedFile.PSProvider.Name -ne 'FileSystem' -or
$selectedFile.Extension -notin $supportedExtensions) {
throw 'Unsupported file input.'
}
}
else {
if ([string]::IsNullOrWhiteSpace($DirectoryPath)) { throw 'Missing directory path.' }
$directory = Get-Item -LiteralPath $DirectoryPath -ErrorAction Stop
if (-not $directory.PSIsContainer -or $directory.PSProvider.Name -ne 'FileSystem') {
throw 'A filesystem directory is required.'
}
}
}
catch {
Write-UploadError $inputError
exit 1
}
$processed = 0L $processed = 0L
$succeeded = 0L $succeeded = 0L
$failed = 0L $failed = 0L
@@ -183,25 +223,32 @@ $endpoint = 'https://api.imgbb.com/1/upload'
$originalSecurityProtocol = [Net.ServicePointManager]::SecurityProtocol $originalSecurityProtocol = [Net.ServicePointManager]::SecurityProtocol
try { try {
$directory = Get-Item -LiteralPath $DirectoryPath -ErrorAction Stop
if (-not $directory.PSIsContainer -or $directory.PSProvider.Name -ne 'FileSystem') {
throw 'A filesystem directory is required.'
}
if (-not $DryRun -and $PSVersionTable.PSVersion.Major -eq 5) { if (-not $DryRun -and $PSVersionTable.PSVersion.Major -eq 5) {
[Net.ServicePointManager]::SecurityProtocol = $originalSecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 [Net.ServicePointManager]::SecurityProtocol = $originalSecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
} }
$mode = if ($DryRun) { 'Dry run' } else { 'Upload' } $mode = if ($DryRun) { 'Dry run' } else { 'Upload' }
if ($useFilePath) {
Write-Status "$mode started. Single file: $($selectedFile.FullName)."
}
else {
Write-Status "$mode started. Recursive search: $([bool]$Recurse)." Write-Status "$mode started. Recursive search: $([bool]$Recurse)."
}
if (-not $DryRun) { if (-not $DryRun) {
$waitMode = if ($useRandomWait) { 'Random (3-6 seconds)' } else { 'Off (retry waits still apply)' } $waitMode = if ($useRandomWait) { 'Random (3-6 seconds)' } else { 'Off (retry waits still apply)' }
Write-Status "Request delay: $waitMode." Write-Status "Request delay: $waitMode."
} }
# Both modes feed the same preparation/upload pipeline; directory mode
# continues to stream files instead of collecting the full list in memory.
$getSelectedImages = {
if ($useFilePath) { $selectedFile }
else {
Get-ChildItem -LiteralPath $directory.FullName -File -Recurse:$Recurse -ErrorAction Stop | Get-ChildItem -LiteralPath $directory.FullName -File -Recurse:$Recurse -ErrorAction Stop |
Where-Object { $_.Extension -in @('.jpg', '.jpeg', '.png') } | Where-Object { $_.Extension -in $supportedExtensions }
ForEach-Object { }
}
& $getSelectedImages | ForEach-Object {
$image = $_ $image = $_
$processed++ $processed++
$base64Image = $null $base64Image = $null
@@ -301,7 +348,7 @@ try {
} }
catch { catch {
$runFailed = $true $runFailed = $true
Write-UploadError 'Run stopped. Check the directory and its permissions; if requests failed, check the API key, connection, or service availability before restarting.' Write-UploadError 'Run stopped. Check the selected input and its permissions; if requests failed, check the API key, connection, or service availability before restarting.'
} }
finally { finally {
if ($PSVersionTable.PSVersion.Major -eq 5) { if ($PSVersionTable.PSVersion.Major -eq 5) {
+33 -7
View File
@@ -1,13 +1,13 @@
# Upload Images to ImgBB # Upload Images to ImgBB
A small PowerShell hobby script for uploading JPG, JPEG, and PNG files from a local directory to ImgBB through its HTTPS API. A small PowerShell hobby script for uploading one JPG, JPEG, or PNG file, or matching files from a local directory, to ImgBB through its HTTPS API.
Uploads run sequentially, with random delays enabled by default and bounded retries to reduce server load. Ordinary delays can be disabled explicitly; retry waits remain enabled. There is no configured limit on the number of files in a run. Service limits, available memory, network conditions, and processing time still apply. Uploads run sequentially, with random delays enabled by default and bounded retries to reduce server load. Ordinary delays can be disabled explicitly; retry waits remain enabled. There is no configured limit on the number of files in a run. Service limits, available memory, network conditions, and processing time still apply.
## Requirements ## Requirements
- Windows PowerShell 5.1 or PowerShell 7. The implementation targets both versions; runtime compatibility testing has not yet been completed. - Windows PowerShell 5.1 or PowerShell 7. The implementation targets both versions; runtime compatibility testing has not yet been completed.
- A readable local filesystem directory containing images. - A readable local image file or filesystem directory containing images.
- An ImgBB API key, including for dry runs. - An ImgBB API key, including for dry runs.
- Internet access to `https://api.imgbb.com/1/upload` for actual uploads. - Internet access to `https://api.imgbb.com/1/upload` for actual uploads.
@@ -43,15 +43,18 @@ The examples use placeholders, not working credentials. Typing a real key into a
| Parameter | Type | Default | Behavior | | Parameter | Type | Default | Behavior |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| `-DirectoryPath` | String | Required | Existing filesystem directory, interpreted literally. Relative paths are resolved from the current working directory. | | `-DirectoryPath` | String | Unset | Existing filesystem directory, required unless `-FilePath` is supplied. Ignored when `-FilePath` is supplied. |
| `-FilePath` | String | Unset | One existing JPG/JPEG/PNG file. Takes precedence over `-DirectoryPath`. Paths are literal; relative paths use the current working directory. |
| `-ApiKey` | String | Unset | A nonblank value takes precedence over `IMGBB_API_KEY`. | | `-ApiKey` | String | Unset | A nonblank value takes precedence over `IMGBB_API_KEY`. |
| `-Recurse` | Switch | Off | Include subdirectories. | | `-Recurse` | Switch | Off | Include subdirectories in directory mode. Ignored in single-file mode. |
| `-WaitTime` | String | `Random` | Only `Off` disables the ordinary 3–6 second request delay. Missing, empty, or unrecognized values retain random waiting. Case-insensitive. Retry waits remain enabled. | | `-WaitTime` | String | `Random` | Only `Off` disables the ordinary 3–6 second request delay. Missing, empty, or unrecognized values retain random waiting. Case-insensitive. Retry waits remain enabled. |
| `-Silent` | Switch | Off | Print errors and skips only. Suppress progress, success URLs, retry notices, and the summary. | | `-Silent` | Switch | Off | Print errors and skips only. Suppress progress, success URLs, retry notices, and the summary. |
| `-DryRun` | Switch | Off | Perform local preparation without sending requests or waiting between files. | | `-DryRun` | Switch | Off | Perform local preparation without sending requests or waiting between files. |
Switches can be combined. For example, `-Recurse -Silent -DryRun` checks the directory tree and displays only problems. Switches can be combined. For example, `-Recurse -Silent -DryRun` checks the directory tree and displays only problems.
Supply `-FilePath` or `-DirectoryPath`. If both are present, **only the file is processed**; the directory is not inspected or validated. An explicitly supplied but empty, missing, inaccessible, or unsupported file path produces an error and exit code `1`; it never falls back to uploading a directory. If neither input is supplied, the script exits with an error. Input validation occurs after the API-key presence check.
`-WaitTime` intentionally accepts arbitrary string values and falls back to `Random` unless the value is exactly `Off`, ignoring letter case. Thus `-WaitTime 'invalid'`, `-WaitTime ''`, and omitting the parameter all keep random waiting. Supply a value when writing `-WaitTime`; a bare parameter without a value remains a PowerShell argument-binding error. A misspelled parameter name is also a binding error. `-WaitTime` intentionally accepts arbitrary string values and falls back to `Random` unless the value is exactly `Off`, ignoring letter case. Thus `-WaitTime 'invalid'`, `-WaitTime ''`, and omitting the parameter all keep random waiting. Supply a value when writing `-WaitTime`; a bare parameter without a value remains a PowerShell argument-binding error. A misspelled parameter name is also a binding error.
If `-ApiKey` is omitted, empty, or whitespace, the script uses `IMGBB_API_KEY`. If neither supplies a nonblank key, the script exits with an error before scanning files. If `-ApiKey` is omitted, empty, or whitespace, the script uses `IMGBB_API_KEY`. If neither supplies a nonblank key, the script exits with an error before scanning files.
@@ -60,6 +63,26 @@ The standard PowerShell common parameters are also available, but `-WhatIf` and
## Examples ## Examples
Upload one file:
```powershell
.\Upload-ImagesToImgBB.ps1 -FilePath 'C:\Images\photo.jpg'
```
Preview one file without uploading:
```powershell
.\Upload-ImagesToImgBB.ps1 -FilePath 'C:\Images\photo.jpg' -DryRun
```
When both paths are supplied, upload only the file:
```powershell
.\Upload-ImagesToImgBB.ps1 -FilePath 'C:\Images\photo.jpg' -DirectoryPath 'C:\OtherImages' -Recurse
```
In this example, `C:\OtherImages` and `-Recurse` are ignored. `-ApiKey`, `-Silent`, `-DryRun`, and `-WaitTime` work in both modes. A successful single-file upload has no ordinary inter-request delay because it needs only one request; retries still follow the configured delay and backoff rules.
Include subdirectories: Include subdirectories:
```powershell ```powershell
@@ -114,9 +137,9 @@ Get-Help .\Upload-ImagesToImgBB.ps1 -Full
## File selection and preparation ## File selection and preparation
- Matches `.jpg`, `.jpeg`, and `.png` extensions, case-insensitively. - Matches `.jpg`, `.jpeg`, and `.png` extensions, case-insensitively.
- Processes only the selected directory unless `-Recurse` is present. - With `-FilePath`, processes only the selected file. Otherwise, processes only the selected directory unless `-Recurse` is present.
- Does not request hidden files through `-Force`. - Does not request hidden files through `-Force`.
- Accepts brackets and other wildcard characters in directory names as literal characters. - Accepts brackets and other wildcard characters in input paths as literal characters; wildcard expansion is not supported.
- Requires a nonempty file no larger than **32 MiB (33,554,432 bytes)**. This is the script's local check; it does not guarantee that the service accepts a file. - Requires a nonempty file no larger than **32 MiB (33,554,432 bytes)**. This is the script's local check; it does not guarantee that the service accepts a file.
- Checks size before and after reading, then converts the file to Base64. - Checks size before and after reading, then converts the file to Base64.
- Does not decode images or verify that file contents match their extensions. - Does not decode images or verify that file contents match their extensions.
@@ -171,7 +194,7 @@ Ordinary messages use `Write-Host`. Error and skip messages use plain .NET stand
An empty, oversized, unreadable, or unencodable image produces a skip message. The file counts as failed, and processing continues. Size failures report the byte count; other preparation failures report the underlying exception type without dumping the exception or image contents. An empty, oversized, unreadable, or unencodable image produces a skip message. The file counts as failed, and processing continues. Size failures report the byte count; other preparation failures report the underlying exception type without dumping the exception or image contents.
A missing/inaccessible directory, enumeration failure, access-denied API status, or exhausted transient retries stops the run. A recursive scan can stop if it encounters an inaccessible directory. Files already uploaded remain uploaded. An invalid selected input, enumeration failure, access-denied API status, or exhausted transient retries stops the run. A recursive scan can stop if it encounters an inaccessible directory. Files already uploaded remain uploaded. In single-file mode, local preparation failures still produce the same skip message and failed count; there is simply no next file to process.
The normal summary contains `processed`, `uploaded`, and `failed` counts. In dry-run mode, `ready` replaces `uploaded`. A stopped run counts only files reached before the stop; it does not count the unvisited remainder. Some configuration failures occur before a summary can be printed. The normal summary contains `processed`, `uploaded`, and `failed` counts. In dry-run mode, `ready` replaces `uploaded`. A stopped run counts only files reached before the stop; it does not count the unvisited remainder. Some configuration failures occur before a summary can be printed.
@@ -194,6 +217,8 @@ Invoke the script normally or in a separate PowerShell process; do not dot-sourc
| Symptom | What to check | | Symptom | What to check |
| --- | --- | | --- | --- |
| API key missing | Set `IMGBB_API_KEY` in the same session or provide `-ApiKey`. Dry runs also require a key. | | API key missing | Set `IMGBB_API_KEY` in the same session or provide `-ApiKey`. Dry runs also require a key. |
| FilePath input error | Check that the selected path is an accessible JPG/JPEG/PNG file. If `-FilePath` is supplied, the directory is ignored even when the file input is invalid. |
| Missing input | Supply `-FilePath` or `-DirectoryPath`. |
| No matching files | Check the path, extensions, hidden attributes, and whether `-Recurse` is needed. | | No matching files | Check the path, extensions, hidden attributes, and whether `-Recurse` is needed. |
| Size skip | Confirm the file is nonempty and at or below the script's 32 MiB threshold. | | Size skip | Confirm the file is nonempty and at or below the script's 32 MiB threshold. |
| Cannot read or encode | Check the reported exception type, file permissions, availability, locks, and memory. | | Cannot read or encode | Check the reported exception type, file permissions, availability, locks, and memory. |
@@ -227,6 +252,7 @@ Before relying on it for a large batch:
1. Run a dry run on a small directory, including an empty file and a nested directory. 1. Run a dry run on a small directory, including an empty file and a nested directory.
2. Confirm that `-Recurse`, `-Silent`, skip messages, colors, and exit codes behave as expected in your terminal. In a mocked upload test, verify that `-WaitTime Off` skips only ordinary delays, while omitted/invalid values retain them and retry waits remain active. 2. Confirm that `-Recurse`, `-Silent`, skip messages, colors, and exit codes behave as expected in your terminal. In a mocked upload test, verify that `-WaitTime Off` skips only ordinary delays, while omitted/invalid values retain them and retry waits remain active.
Also check single-file mode, file-over-directory precedence, and invalid file input without directory fallback.
3. Upload a small, non-sensitive test image and check the returned URL. 3. Upload a small, non-sensitive test image and check the returned URL.
4. Validate retry and failure paths using mocks or a controlled test harness rather than deliberately overloading the live service. 4. Validate retry and failure paths using mocks or a controlled test harness rather than deliberately overloading the live service.