Public/Branding/Set-CIBrandingTheme.ps1

function Set-CIBrandingTheme(){
    <#
    .SYNOPSIS
    Uploads a new (or replaces existing) CSS theme for vCloud Director.

    .DESCRIPTION
    Uploads a new (or replaces existing) CSS theme for vCloud Director.

    .PARAMETER ThemeName
    The Theme Name

    .PARAMETER CssFile
    The filename of the CSS file generated bythe VMware theme-generator code which will be uploaded.

    .EXAMPLE
    Set-CIBrandingTheme -Theme Example -CssFile example.css


    .NOTES
    These cmdlets were refactored based on the original work of Jon Waite. The original implementation is available from https://raw.githubusercontent.com/jondwaite/vcd-h5-themes/master/vcd-h5-themes.psm1

    Per-tenant branding requires functionality first introduced in vCloud Director 9.7 (API Version 32.0) and will *NOT* work with any prior release.
    #>

    Param(
        [Parameter(Mandatory=$True)]
            [ValidateNotNullorEmpty()]  [string] $ThemeName,
        [Parameter(Mandatory=$True)]
            [ValidateNotNullorEmpty()]  [string] $CssFile
    )
    # Always check if we are connected first
    Test-CIServerConnection | Out-Null

    # Check if the theme exists & the CSS file provided exists
    if((Get-CIBrandingThemes -ThemeName $ThemeName).Count -eq 0){
        throw "A Theme with the name $ThemeName does not exists in the currently connected environment."
    }
    if (!(Test-Path -Path $CssFile)){
        throw "Error, could not locate css theme file: $CssFile."
    }
    # Build an object with the Path Name for the first API call
    $CssFileName = $CssFile | Split-Path -Leaf
    $Data = [PSCustomObject]@{
        fileName = $CssFileName
        size = ((Get-Item $CssFile).Length)
    }

    # Define basic request properties for the API call to get the upload path
    [Hashtable] $RequestParameters = @{
        URI = "$($global:DefaultCIServers.CloudAPIServiceURI)/branding/themes/$ThemeName/contents"
        Method = "Post"
        APIVersion = 33
        Data = ($Data | ConvertTo-Json)
    }
    $Response = (Invoke-CICloudAPIRequest @RequestParameters)

    # Extract the upload URI from the returned headers
    $UploadURI = [Regex]::new("(?<=<).*(?=>)").match($Response.Headers.Link).Value
    [Hashtable] $PutRequest = @{
        URI = $UploadURI
        Method = "Put"
        Headers = @{
            "x-vcloud-authorization" = $global:DefaultCIServers.SessionId
            "Accept" = "application/json;version=33.0"
        }
        InFile = $CssFile
    }
    try {
        Invoke-WebRequest @PutRequest
    } catch {
        throw "Error occurred obtaining uploading CSS file, Status Code is $($_.Exception.Response.StatusCode.Value__)."
    }
}