Export CSV file and download

Is there a way to download a file on a UD Button ?

Not directly through a button since it uses WebSockets and isn’t really an HTTP request.

You could write your CSV to a folder served with Publish-UDFolder and then use New-UDElement to create a button that, when clicked, downloads the CSV.

Since a button is just an anchor tag, your custom button could have an href attribute that points to the CSV file.

Hey @adam the link are dead and i’ve the same issue, i want to create a Download button, so i search in the doc and use Publish-UDFolder i try 2 things :

New-UDButton -Icon “save” -Id “dl” -Text “TĂ©lĂ©charger Csv” -OnClick {
New-UDHtml -Markup “<a href:‘/Fichier/inactivecomp_groupe.csv’ Download”
Show-UDToast -Message “TĂ©lĂ©chargement en cours”
}

And

New-UDButton -Icon “save” -Id “dl” -Text “TĂ©lĂ©charger Csv” -OnClick {
Invoke-WebRequest -Uri http://localhost:8090/Fichier/inactivecomp_groupe.csv
Show-UDToast -Message “TĂ©lĂ©chargement en cours”
}

But none of both work. Any Idea why ?

EDIT : I try too

New-UDLink -Url “Fichier/inactivecomp_groupe.csv”

Hi @papasoulman1 if you download the latest build which is here:-


Then make sure you download the SOURCE CODE.ZIP
Then in there Adam has been kind enough to put a demo of this with the files required:-
universal-dashboard-nightly.20190618.4\examples\published-folders

1 Like

I also just wrote a blog post about this: https://ironmansoftware.com/serving-files-with-universal-dashboard/

Hi Adam, I have been trying to use this for a while today and getting slightly frustrated with it
 If i use your code snippet for dynamic file downloads locally in PowerShell it works fine. Through IIS it will create the new file in the location with content, but will not then download it and the wheel just spins

Even if i add a direct link to a previously created file it still just spins and no output:
New-UDInputAction -Content (
New-UDElement -Tag ‘a’ -Attributes @{
‘href’ = “http://###URL###/Share/blah.txt”
‘download’ = “blah.txt”
className = “btn”
} -Content {
“Download”
}
)

I can confirm that if i go to the URL for this text file it works, and if i add a UDLink to this page, it also works:
New-UDLink -Text “Download” -Url http://###URL###/Share/blah.txt

Any help would be appreciated.

When you say the wheel spins, do you mean the UDInput?

Can you post the rest of your UDInput code? It could be an error in the Endpoint code that’s causing a problem. You could also try to gather a log using Enable-UDLogging to see if anything is going on there.

Hi Adam, I have it wrong above it is not even working for me on a local dashboard, i have to be doing something wrong!!

If i run the file below, the first link (UD-Column) creates a file, download it fine, then the second, which is the example doesn’t, the UDInput just spins


Get-UDDashboard | Stop-Uddashboard

$SharePath = "$PSScriptRoot\share"
$EndpointInit = New-UDEndpointInitialization -Variable "SharePath" 
$Dashboard = New-UDDashboard -Title 'Downloads' -Content {
    New-UDColumn -Endpoint {
        $FileName = (New-Guid).ToString() + ".txt"
        $FullFileName = Join-Path $SharePath $FileName
        "TEST" | Out-File -FilePath $FullFileName
        New-UDElement -Tag 'a' -Attributes @{
            'href' = "http://localhost:10000/share/$FileName"
            'download' = 'myFileName.txt'
        } -Content {
            "Download TESTColumn $Filename..."
        }
    }

    New-UDInput -Title "Create File" -Endpoint {
        param($FileContents)
        $FileName = (New-Guid).ToString() + ".txt"
        $FullFileName = Join-Path $SharePath $FileName
        $FileContents | Out-File -FilePath $FullFileName
        New-UDInputAction -Content (
            New-UDElement -Tag 'a' -Attributes @{
                'href' = "http://localhost:10000/share/$FileName"
                'download' = "myFileName.txt"
                className = "btn"
            } -Content {
                "Download"
            }
        )
    }
} -EndpointInitialization $EndpointInit

Start-UDDashboard -Dashboard $Dashboard -PublishedFolder $Folder -Port 10000

I don’t see anything obviously wrong with this. Can you please enable logging?

Just plop this at the top of your file and then try to use the UDInput. The output will go right into the console.

Enable-UDLogging

14:38:22 [Info] Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker Executed action method UniversalDashboard.Controllers.ComponentController.Input (UniversalDashboard), returned result Microsoft.AspNetCore.Mvc.JsonResult in 158.003ms.
14:38:22 [Info] Microsoft.AspNetCore.Mvc.Formatters.Json.Internal.JsonResultExecutor Executing JsonResult, writing value of type ‘System.Object’.
14:38:22 [Info] Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker Executed action UniversalDashboard.Controllers.ComponentController.Input (UniversalDashboard) in 249.9135ms
14:38:22 [Error] Microsoft.AspNetCore.Server.Kestrel Connection id “0HLQMUKB6R4LV”, Request id “0HLQMUKB6R4LV:00000006”: An unhandled exception was thrown by the application.
14:38:22 [Info] Microsoft.AspNetCore.Hosting.Internal.WebHost Request finished in 267.7221ms 200 application/json; charset=utf-8

I also get this same line in the IIS UDLogging: [Error] Microsoft.AspNetCore.Server.Kestrel Connection id

I can reproduce this. Looking into it now.

1 Like

It’s a serialization issue. Can’t believe this wasn’t run into earlier. I have PR in for it here: https://github.com/ironmansoftware/universal-dashboard/pull/1277

I think they call it the law of sod! Thankyou for jumping on this so quickly!

Can you please post here when its fixed? (not sure how bugs work here).

This will be in tonight’s nightly build so you can test it out tomorrow. Nightly builds are posted here: https://github.com/ironmansoftware/universal-dashboard/releases

You can install nightly builds using this script: https://github.com/ironmansoftware/universal-dashboard/blob/master/tools/install-nightly.ps1

The 2.7 release is scheduled for next Monday the 28th. Then it will be available on the PowerShell Gallery.

3 Likes

Hi Adam,

Serving files is one thing. Allowing users to upload files another. Are there plans to include this functionality in UD?

You can upload files using New-UDInput. When you create a input use New-UDInputField and use either the File or BinaryFile type. New-UDEndpoint for REST APIs also work with files as of 2.7

Great, will this soon.

Thanks.

Hi,

I’m face with a very strange issue, instead of download the actual file I end up with a HTML code inside the csv file download here
If I look at the location where the file is downloaded then I have a valid csv file in that location with the correct content.So something goes wrong during the download.
Could someone please help with this is a very strange issue that is blocking me project to go forward.

my code :
New-UDElement -Tag ‘a’ -Attributes @{
‘href’ = “http://localhost:10012/files/$FileName”
‘download’ = $FileName
className = “btn-flat”
} -Content {
“Download”
}

Entire function code :

Function Invoke-ButtonClick {

     param(

          $Cluster,

          [String]$Mode

     )

    $DsReport = New-Object System.Collections.ArrayList

    $DrsReport = New-Object System.Collections.ArrayList

    $CsvDelimiter  = ";"

     $DSlist = Get-Datastore -RelatedObject $Cluster -Server $VCSession

    If ($Mode -eq "Datastore") {  

        $FileName = "$($Cluster.Name)" + "_Datastore.csv"

        $Url = 'http://localhost:10012/files/' + $FileName

        Show-UDModal -Height 100% -Width 90% -Content {

                New-UDTable -Title "Datastore Info Cluster $($Cluster.Name)" -Headers @('Name', 'VM Count', 'Percentage Free Space(%)') -Content {

                    Foreach ($DS in $DSlist){

                        $VMcount = (Get-VM -Datastore $DS -Server $VCSession).Count 

                                      

                         $DsObject = New-Object PsObject -property @{

                            'Datastore' = $DS.Name

                            'VM-Count' =  If ($VMcount -gt 0){$VMcount}Else{"No VMs"}

                            'Free' = [math]::Round(($DS.FreeSpaceGB)/($ds.CapacityGB)*100,2)

                        }  

                        

                        $DsObject | Out-UDTableData -Property @('Datastore','VM-Count','Free')

                        $DsReport.Add($DsObject) | Out-Null                                                           

                    }           

                }

                $DsExpFullPath = Join-Path -Path $ExpPath -ChildPath "\$($FileName)"

                $DsReport | Select-Object "Datastore", "VM-Count", "Free" | Export-csv -NoTypeInformation -Path $DsExpFullPath -Delimiter $CsvDelimiter

            } -FixedFooter -Footer {

                New-UDElement -Tag 'a' -Attributes @{

                    'href' = $Url

                    'download' = $FileName

                } -Content {

                    "Download"

                }

                New-UDButton -Text "Close" -Flat -OnClick {Hide-UDModal}

            } 

 

    }Else {

        $FileName = "$($Cluster.Name)" + "_Datastore.csv"

        $Url = 'http://localhost:10012/files/' + $FileName

        Show-UDModal -Height 100% -Width 90% -Content {

            New-UDTable -Title "DRS Info Cluster $($Cluster.Name)" -Headers @('VMName', 'VMHost', 'Datastore', 'DRS Group', 'DRSGroupType') -Content {

                    $VMList = $Cluster | Get-VM -Server $VCSession | Where-Object {$_.Name -ne "DRS_DONOTSTART"}

                    Foreach($VM in $VMList) {

                            $DRSGroups = Get-DrsClusterGroup -VM $VM -Server $VCSession

                            $Datastore = Get-Datastore -VM $VM -Server $VCSession

                         $DrsObject = New-Object PsObject -property @{

                                'VMName' = $VM.Name

                                'VMHost' = $VM.VMHost.Name

                                'Datastore' = $Datastore.Name

                                'DRSGroupName' = if ($DRSGroups){

                                                    if($DRSGroups.Count -gt 1){

                                                        [string]::Join(",",$DRSGroups.Name)

                                                                                                             

                                                    }else{

                                                        $DRSGroups.Name

                                                    }

                                                    

                                                 }else{

                                                    "No DRS Group"

                                                 }

                                'DRSGroupType' =  If ($DRSGroups){

                                                    if($DRSGroups.Count -gt 1){

                                                            [string]::Join(",",$DRSGroups.GroupType)

                                                            

                                                        }else{

                                                            $DRSGroups.GroupType.Tostring()

                                                    }

                                                }Else{"No DRS Group"}

                            }

                                

                            $DrsObject | Out-UDTableData -Property @('VMName', 'VMHost', 'Datastore', 'DRSGroupName', 'DRSGroupType')

                            $DrsReport.Add($DrsObject) | Out-Null                                                    

                    }         

            }

            $DsExpFullPath = Join-Path -Path $ExpPath -ChildPath "\$($FileName)"

            $DrsReport | Select-Object "Datastore", "VM-Count", "Free" | Export-csv -NoTypeInformation -Path $DsExpFullPath -Delimiter $CsvDelimiter

        } -FixedFooter -Footer {

            New-UDElement -Tag 'a' -Attributes @{

                'href' = $Url

                'download' = $FileName

            } -Content {

                "Download"

            }

            New-UDButton -Text "Close" -Flat -OnClick {Hide-UDModal}

        } 

    }

}

Thanks

Hi @coopmal1,

Looks like your URL is incorrect.
Does the CSV file reside in a published folder, publicly avalaible?
Can you reach the contents directly by pasting the URL in your browser?