Skip to content

Commit d4ae380

Browse files
Fixed file parameters setting.
1 parent bce5b5d commit d4ae380

File tree

1 file changed

+92
-32
lines changed

1 file changed

+92
-32
lines changed

ConvertApi/ConvertApi.psm1

Lines changed: 92 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ Converts (or merges) files via ConvertAPI v2 REST, supporting multiple files/URL
6060
- Single URL => passes ?Url=... as a query parameter.
6161
- Extra API params via -Parameters.
6262
- Use -StoreFile to get time-limited URLs for downloading.
63+
- File-typed parameters: any -Parameters key that ends with 'File' is treated as a file input
64+
when its value is a local path; triggers multipart automatically.
65+
66+
- Use -InputMode to control how inputs are sent:
67+
* Auto (default): 1 input -> single-file; 2+ inputs -> Files[i] multipart
68+
* File force single-file (exactly 1 input required)
69+
* Files force Files[i] multipart (even for 1 input)
6370
6471
.EXAMPLE
6572
Invoke-ConvertApi -From pdf -To merge -File .\a.pdf, .\b.pdf -OutputPath .\out -StoreFile
@@ -86,7 +93,9 @@ https://www.convertapi.com/a/authentication
8693
[string]$Token, # overrides env/module token
8794
[int]$TimeoutSec = 300,
8895
[switch]$Overwrite,
89-
[switch]$PassThru
96+
[switch]$PassThru,
97+
98+
[ValidateSet('Auto','File','Files')] [string]$InputMode = 'Auto'
9099
)
91100

92101
begin {
@@ -146,7 +155,7 @@ https://www.convertapi.com/a/authentication
146155
$streams = @()
147156

148157
try {
149-
# Add files
158+
# Add file parts
150159
foreach ($kv in $FilesTable.GetEnumerator()){
151160
$path = $kv.Value
152161
$stream = [System.IO.File]::OpenRead($path)
@@ -158,12 +167,10 @@ https://www.convertapi.com/a/authentication
158167
$content.Add($sc)
159168
}
160169

161-
# Add URLs as string fields (Files[i] = 'https://...')
170+
# Add extra "string" parts (includes Files[i] urls, Url, StoreFile, Parameters, etc.)
162171
foreach ($kv in $UrlsTable.GetEnumerator()){
163-
$content.Add([System.Net.Http.StringContent]::new($kv.Value), $kv.Key)
172+
$content.Add([System.Net.Http.StringContent]::new([string]$kv.Value), $kv.Key)
164173
}
165-
166-
# Add extra fields (StoreFile, Parameters...)
167174
foreach ($kv in $Fields.GetEnumerator()){
168175
$content.Add([System.Net.Http.StringContent]::new([string]$kv.Value), $kv.Key)
169176
}
@@ -186,66 +193,117 @@ https://www.convertapi.com/a/authentication
186193
}
187194
}
188195

189-
# Common query/form params
196+
# Common query/form params (cloned later for multipart)
190197
$common = @{}
191198
if ($StoreFile.IsPresent) { $common["StoreFile"] = "true" }
192199
if ($Parameters) { foreach ($k in $Parameters.Keys) { $common[$k] = $Parameters[$k] } }
193200
}
194201

195202
process {
196-
$fileCount = @($File).Count
197-
$urlCount = @($Url).Count
198-
if ($fileCount -eq 0 -and $urlCount -eq 0) {
199-
throw "Provide at least one -File or -Url."
203+
# Safe counts (avoid @($null).Count = 1)
204+
$fileCount = if ($PSBoundParameters.ContainsKey('File') -and $null -ne $File) { $File.Count } else { 0 }
205+
$urlCount = if ($PSBoundParameters.ContainsKey('Url') -and $null -ne $Url) { $Url.Count } else { 0 }
206+
$inputTotal = $fileCount + $urlCount
207+
if ($inputTotal -lt 1 -and -not $Parameters) { throw "Provide at least one -File or -Url." }
208+
209+
# Detect extra file-typed parameters (keys ending with 'File')
210+
$fileParamKeys = @()
211+
if ($Parameters) {
212+
foreach ($k in $Parameters.Keys) {
213+
if ($k -match '(?i)File$') { $fileParamKeys += $k }
214+
}
215+
}
216+
217+
# Decide how to send primary inputs
218+
$useFilesArray = switch ($InputMode) {
219+
'Files' { $true } # force Files[i]
220+
'File' { if ($inputTotal -ne 1) { throw "InputMode 'File' requires exactly one input, but $inputTotal were provided." }; $false }
221+
default { $inputTotal -ge 2 } # Auto: Files[i] only when 2+ inputs
200222
}
201223

202-
# MULTI-INPUT (merge etc.) via HttpClient multipart —— PS 5.1 safe
203-
if ($fileCount + $urlCount -gt 1) {
204-
$uri = New-ConvertApiUri -From $From -To $To -Parms $null
224+
# Using multipart: we either use Files[i] OR we have any File-typed parameters
225+
$needsMultipart = $useFilesArray -or ($fileParamKeys.Count -gt 0)
205226

206-
# Build Files[i] in order
227+
if ($needsMultipart) {
228+
$uri = New-ConvertApiUri -From $From -To $To -Parms $null
207229
$filesTable = [ordered]@{}
208-
$urlsTable = [ordered]@{}
209-
$i = 0
210-
foreach ($p in $File) {
211-
if (-not (Test-Path $p)) { throw "Input not found: $p" }
212-
$resolved = (Resolve-Path $p).Path
213-
$filesTable["Files[$i]"] = $resolved
214-
$i++
230+
$stringParts = [ordered]@{} # Url, Files[i] urls, StoreFile, other non-file params
231+
232+
# Primary inputs
233+
if ($useFilesArray) {
234+
# Files[i] … for local files
235+
$i = 0
236+
foreach ($p in ($File | Where-Object { $_ })) {
237+
if (-not (Test-Path $p)) { throw "Input not found: $p" }
238+
$filesTable["Files[$i]"] = (Resolve-Path $p).Path
239+
$i++
240+
}
241+
# Files[i] … for url inputs (as strings)
242+
foreach ($u in ($Url | Where-Object { $_ })) {
243+
$stringParts["Files[$i]"] = $u
244+
$i++
245+
}
246+
} else {
247+
# Single primary input carried as 'File' or 'Url' in multipart
248+
if ($fileCount -eq 1 -and $urlCount -eq 0) {
249+
if (-not (Test-Path $File[0])) { throw "Input not found: $($File[0])" }
250+
$filesTable["File"] = (Resolve-Path $File[0]).Path
251+
} elseif ($urlCount -eq 1 -and $fileCount -eq 0) {
252+
$stringParts["Url"] = $Url[0]
253+
}
215254
}
216-
foreach ($u in $Url) {
217-
$urlsTable["Files[$i]"] = $u
218-
$i++
255+
256+
# Add file-typed parameters (…File). If value is a local path -> file part; otherwise send as string
257+
if ($fileParamKeys.Count -gt 0) {
258+
foreach ($k in $fileParamKeys) {
259+
$v = $Parameters[$k]
260+
$vals = @()
261+
if ($v -is [System.Collections.IEnumerable] -and -not ($v -is [string])) { $vals = @($v) } else { $vals = @($v) }
262+
$idx = 0
263+
foreach ($item in $vals) {
264+
if ($item -and (Test-Path $item)) {
265+
$partName = if ($idx -eq 0) { $k } else { "$k[$idx]" }
266+
$filesTable[$partName] = (Resolve-Path $item).Path
267+
$idx++
268+
} else {
269+
# URL or plain string → send as string field
270+
$partName = if ($idx -eq 0) { $k } else { "$k[$idx]" }
271+
$stringParts[$partName] = [string]$item
272+
$idx++
273+
}
274+
}
275+
}
219276
}
220277

221-
# Extra fields
278+
# Add remaining simple fields (Parameters + StoreFile) except the ones we already promoted to file/string parts above
222279
$fields = [ordered]@{}
223280
foreach ($k in $common.Keys) {
281+
if ($fileParamKeys -contains $k) { continue } # skip; already added as file/string parts
224282
$v = $common[$k]; if ($v -is [bool]) { $v = $v.ToString().ToLower() }
225283
$fields[$k] = [string]$v
226284
}
227285

228-
$label = ("{0} item(s)" -f ($fileCount + $urlCount))
286+
$label = ("{0} item(s)" -f [Math]::Max($inputTotal,1))
229287
if ($PSCmdlet.ShouldProcess($label, "Convert $From -> $To (multipart)")) {
230-
$response = Invoke-ConvertApiMultipart -Uri $uri -FilesTable $filesTable -UrlsTable $urlsTable -Fields $fields -Token $Token -TimeoutSec $TimeoutSec
288+
$response = Invoke-ConvertApiMultipart -Uri $uri -FilesTable $filesTable -UrlsTable $stringParts -Fields $fields -Token $Token -TimeoutSec $TimeoutSec
231289
Save-ConvertApiFiles $response
232290
}
233291
return
234292
}
235293

236-
# SINGLE URL
294+
# ---- Single URL (query string) ----
237295
if ($urlCount -eq 1 -and $fileCount -eq 0) {
238296
$q = $common.Clone(); $q["Url"] = $Url[0]
239297
$uri = New-ConvertApiUri -From $From -To $To -Parms $q
240-
if ($PSCmdlet.ShouldProcess($Url[0], "Convert $From -> $To (url)")) {
298+
if ($PSCmdlet.ShouldProcess($Url[0], "Convert $From -> $To (single url)")) {
241299
$response = Invoke-RestMethod -Uri $uri -Method POST -Headers $headers -TimeoutSec $TimeoutSec
242300
Save-ConvertApiFiles $response
243301
}
244302
return
245303
}
246304

247-
# SINGLE LOCAL FILE (octet-stream)
248-
if ($fileCount -eq 1) {
305+
# ---- Single local file (octet-stream + Content-Disposition) ----
306+
if ($fileCount -eq 1 -and $urlCount -eq 0) {
249307
$resolved = (Resolve-Path $File[0]).Path
250308
$name = [IO.Path]::GetFileName($resolved)
251309
$bytes = [IO.File]::ReadAllBytes($resolved)
@@ -261,6 +319,8 @@ https://www.convertapi.com/a/authentication
261319
}
262320
return
263321
}
322+
323+
throw "Cannot resolve inputs for the chosen InputMode '$InputMode'."
264324
}
265325
}
266326

0 commit comments

Comments
 (0)