Pode icon indicating copy to clipboard operation
Pode copied to clipboard

Issue #1096 - Add Save-PodeRequestFile functionality - disable overwrite and return filepaths

Open acommonusername opened this issue 2 years ago • 1 comments
trafficstars

Description of the Change

Added functionality to make it possible to disable overwriting files, and instead add a numerical suffix to the filename if it already exists in the directory. Enabled via Switch parameter.

Added functionality to make it possible to return a list of filepaths of the uploaded files. Enabled via Switch parameter.

Help comment updated to include parameters and an example.

Related Issue

Resolves #1096

Examples

Parameter NoOverwrite If supplied, disables overwriting already existing files, and adds a numerical suffix to the filename if necessary. F.x. if C:\pode\test.txt already exists and test.txt is uploaded again, it will be saved as C:\pode\test (1).txt

Parameter Return If supplied, filepaths of all saved files will be returned as a list.

Usage $filePaths = Save-PodeRequestFile -Key 'avatar' -Path 'F:/Images' -NoOverwrite -Return

Result In the above example, if F:/Images already contains test.jpg and you're uploading the files test.jpg and asdf.jpg. test.jpg will be saved as test (1).jpg and asdf.jpg as asdf.jpg, the function will then return a list containing the following filepaths:

F:/Images\test (1).jpg F:/Images\asdf.jpg

acommonusername avatar Apr 30 '23 23:04 acommonusername

Hey @acommonusername,

Thanks for the PR! Looking at this there's quite a few use cases this would have to cover when -NoOverwrite is supplied:

  • File names with no extension: .gitignore
  • File names with multiple .: example.2023.05.11.txt
  • Files being saves to a PS Drive or SMB, in this instance Test-Path has to be used as [Path]::Exists(...) doesn't work
  • Existing file names with the (id) suffix that could range from 1 > 1000 - ie: this would result in 1000 exists checks

I have built something similar once before, and it would be worth moving the "file ID suffix builder" into it's own function in Private/Helpers.ps1; checking if -NoOverwrite was supplied back in Save-PodeRequestFile, and then calling the new function.

Using the logic I've built before, and combing your logic produces the following (which should cover all use-cases above):

param(
    $FilePath = 'C:\temp\tests.txt'
)

# check the initial file path, and use that if it doesn't exist
if (!(Test-Path $filepath)) {
    return $filepath
}

# vars for some regex
$fileRegex = '(.+)(\.(?=[^\\\/\.]+$))'
$idRegex = '^.+? \((?<id>\d+)\).*$'

# split the file path into base path and name
$filepath, $filename = $filepath -split '[\\/](?=[^\\\/]+$)'

# build a wildcard file name pattern for filtering existing files
# the regex check is for ".name" use cases where there is no extension
if ($filename -imatch $fileRegex) {
    $wildFilename = $filename -replace $fileRegex, '$1 (*)$2'
} else {
    $wildFilename = "$($filename) (*)"
}

# calculate the next "id" based on existing files
$nextId = 1
$files = @(Get-ChildItem -Name -File -Force -Path $filepath -Filter $wildFilename |
    Sort-Object -Property { $_.Length },{ $_ })

$lastId = $files[-1] -replace $idRegex, '$1'
if (($file.Length -eq $lastId)) {
    $nextId = $lastId + 1
} else {
    foreach ($file in $files) {
        if (($file -replace $idRegex, '$1') -ne $nextId) {
            break
        }

        $nextId++
    }
}

# generate the new file name
if ($filename -imatch $fileRegex) {
    $filename = $filename -replace $fileRegex, "`$1 ($($nextId))`$2"
} else {
    $filename = "$($filename) ($($nextId))"
}

# combine the new file name with the original base path, and return
$filepath = [System.IO.Path]::Combine($filepath, $filename)
return $filepath

For the -Return flag, you can actually return values directly from the foreach into an array and then return that 😄

# save the files
$filePathsList = @(foreach ($file in $files) {
    # logic

    if ($Return) {
        $filePath
    }
})

if ($Return) {
    return $filePathsList
}

Saves building list objects and appending to them 😉

Badgerati avatar May 11 '23 20:05 Badgerati