mirror of
https://github.com/iminet/dev.git
synced 2026-11-04 10:09:15 +01:00
Added new features for ImgBB_Upload ps script
This commit is contained in:
@@ -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' }
|
||||||
Write-Status "$mode started. Recursive search: $([bool]$Recurse)."
|
if ($useFilePath) {
|
||||||
|
Write-Status "$mode started. Single file: $($selectedFile.FullName)."
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
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."
|
||||||
}
|
}
|
||||||
|
|
||||||
Get-ChildItem -LiteralPath $directory.FullName -File -Recurse:$Recurse -ErrorAction Stop |
|
# Both modes feed the same preparation/upload pipeline; directory mode
|
||||||
Where-Object { $_.Extension -in @('.jpg', '.jpeg', '.png') } |
|
# continues to stream files instead of collecting the full list in memory.
|
||||||
ForEach-Object {
|
$getSelectedImages = {
|
||||||
|
if ($useFilePath) { $selectedFile }
|
||||||
|
else {
|
||||||
|
Get-ChildItem -LiteralPath $directory.FullName -File -Recurse:$Recurse -ErrorAction Stop |
|
||||||
|
Where-Object { $_.Extension -in $supportedExtensions }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
& $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) {
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user