Information: The project I describe can be downloaded from Github: https://github.com/atiedemann/AzFunctions/tree/main/MakeZip

Azure Logic APPs are a very comprehensive tool that provides an extremely large number of functions. However, if you have the task to create a ZIP file in a logic app, it is still only possible with a third-party app “Encodian”. However, this connector transfers the data to its own data center, and this is not desired in many cases.

I use an Azure function in my Logic APPs, which gets the streams via webhook and then converts the individual files to a ZIP file and returns a new stream.

This way the data stays in your tenant, and you have the complete process under control.

Here the function.json file:

{
  "bindings": [
    {
      "authLevel": "function",
      "type": "httpTrigger",
      "direction": "in",
      "name": "Request",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "Response"
    }
  ]
}

And here the run.ps1 PowerShell file

using namespace System.Net
using namespace System.IO.Compression

# Input bindings are passed in via param block.
param(
    $Request, 
    $TriggerMetadata
)

$Values = $Request.RawBody | ConvertFrom-Json 
$PathName = ('{0}\ZipDeploy\{1}' -f $env:temp, (Get-Random -Minimum 1000 -Maximum 9999))
$PathZipFile = ('{0}\{1}' -f $env:temp, (Get-Random -Minimum 1000 -Maximum 9999))
$FileHashes = [System.Collections.Generic.List[PSObject]]::New()

Write-Output '###################################'
Write-Output $Request.RawBody 
Write-Output '###################################'

# Create Directory
Write-Output "Directory creation"
try {
    $null = New-Item -ItemType Directory -Path $PathName -ErrorAction Stop
    $Result = $true
}
catch {
    Write-Output $_.Exception.Message
}

if ($Result -eq $true) {
    foreach ($File in $Values | Where-Object { $_.contentBytes.length -gt 0}) {
        # write file to disk
        $ByteArr = [System.Convert]::FromBase64String($File.contentBytes)
        [System.IO.File]::WriteAllBytes(('{0}\{1}' -f $PathName, $File.Name), $ByteArr)

        # get the item
        $i = Get-Item -Path ('{0}\{1}' -f $PathName, $File.Name)

        # Get file hash
        $Hash = Get-FileHash -Algorithm SHA256 -Path $i.FullName | Select-Object Algorithm,Hash,@{Name="FileName"; E={ ('{0}{1}' -f $_.Hash, $i.Extension) }}
        if ($Hash.Hash.Length -gt 0 -and $Hash.FileName.Length -gt 0)
        {
            $FileHashes.Add($Hash)
        }

        # Rename file
        Rename-Item -Path $i.FullName -NewName ('{0}\{1}{2}' -f $PathName, $Hash.Hash, $i.Extension)
    }
}

if ((Get-ChildItem -Path $PathName -ErrorAction SilentlyContinue).Count -gt 0)
{
    Write-Output "Zip file creation"
    try {
        [System.IO.Compression.ZipFile]::CreateFromDirectory($PathName, $PathZipFile)
        if (Test-Path -Path $PathZipFile -ErrorVariable Stop)
        {
            $ByteArr = [System.Io.File]::ReadAllBytes($PathZipFile)
            $Return = [PSCustomObject]@{
                ContentBytes = [System.Convert]::ToBase64String($ByteArr)
                Hashes = $FileHashes
                Status = 'Success'
            } | ConvertTo-Json
        } else {
            $Return = [PSCustomObject]@{
                ContentBytes = ''
                Hashes = @([PSCustomObject]@{
                    Algorithm = ''
                    FileName = ''
                    Hash = ''
                })
                Status = 'Error'
            } | ConvertTo-Json
        }
    }
    catch {
        Write-Output $_.Exception.Message
    }
} else {
    $Return = [PSCustomObject]@{
        ContentBytes = ''
        Hashes = @([PSCustomObject]@{
            Algorithm = ''
            FileName = ''
            Hash = ''
        })
        Status = 'Error'
    } | ConvertTo-Json
}


# try to remove the files and folder
Write-Output "Remove items"
Remove-Item -Path $PathZipFile -Force -ErrorAction SilentlyContinue
Remove-Item -Path $PathName -Force -ErrorAction SilentlyContinue -Recurse

# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
        StatusCode = [HttpStatusCode]::OK
        Body       = $Return
    })

The JSON-Body that these app is accepting looks like this:

[
    {
      "contentBytes": "xxxyyyvvv",
      "contentType": "image/png",
      "name": "image001.png"
    }
]

Leave a Reply

Your email address will not be published. Required fields are marked *