Download a document with Powershell

Thursday, March 10, 2016

FileHold offers an easy method to access a document from an external application: a document link. The link works in any browser to take the user to the document in the FileHold folder, web viewer, or download the document directly to the browser’s download folder. Sometimes it is desirable to download the document without any user intervention. A tool like Powershell provides some great facility for automating the download and it can also easily interface with the FileHold API to do things like start a FileHold session.

For the purposes of this article I am assuming the reader has some basic skills with Windows administration and Powershell.

The goal is to have something simple that can be run from a command line or automated task. Something like the following, where the Powershell script is FH-Get-File.ps1, 67156 is the FileHold id for the document, and myTempFile.pdf is the name of the temporary file where the document will be copied.

powershell –file FH-Get-File.ps1 –fileHoldId 67156 –tempFile myTempFile.pdf

We will start off defining the parameters. According to this definition the FileHold id must be supplied and the temporary filename is optional. If the temporary filename is left out it will default to tempFile.pdf.

    [string]$tempFile = "tempFile.pdf"

Next we will define some important information about our environment: the address of the FileHold server and the user id and password we will use to login to FileHold. The user we choose must have permissions in FileHold to access the documents you want to download. If this will be automated it would be a good idea to give the user a guaranteed concurrent session.

TIP: This sort of user information added to script is fine for simplicity of this article, but for a production solution it would be better to follow best practices for storing Powershell credentials for automated use.

$fileHoldUrl = "http://fileholdtest4/fh/filehold"
$userId = "sysadm"
$password = "12345"

The next step is to start a FileHold session. The first line is needed to get the value for the custom client type. This path assumes the script is running on the FileHold server. If it is running somewhere else make sure it points to FileHold.Common.dll. This file is available in the FileHold API demos and elsewhere on the FileHold server. Next we will use the magic of Powershell to setup a reference to the FileHold UserRoleManager SessionManager web service in the urmSessionManagerProxy variable. Finally, we will call StartSession.

Add-Type -Path 'C:\Program Files\FileHold Systems\Application Server\fileholdadm\FileHold.Common.dll'
$uri = $fileHoldUrl + "/UserRoleManager/SessionManager.asmx?WSDL"
$urmSessionManagerProxy = New-WebServiceProxy -Uri $uri
$sessionId = $urmSessionManagerProxy.StartSession( $userId, $password, [FileHold.Common.Client]::CustomClient.value__ )

This next step is optional. It affects the contents of the user activity log. The log will display the reported client version in terms of FileHold versions, the name of the script, and the version 4 IP address of the machine the script is running on.

$scriptName = $MyInvocation.MyCommand.Name
$clientVersion = "14.2"
$serverVersion = $null
$compatible = $urmSessionManagerProxy.CheckApiVersionAndLogClientInfo( $sessionId, `
                    $clientVersion, [ref]$serverVersion, `
                    $scriptName, `
                    (get-netadapter | get-netipaddress | ? addressfamily -eq 'IPv4').ipaddress )

Finally we have a session and we are ready to get our file. First we will build the address for the document then we will use the Invoke-WebRequest cmdlet to download the current version of the document and store it in our temporary file name.

The address we will use to get the document comes in two parts. Part one will connect the Invoke-WebRequest with the session we just created. Part two will actually point to the document.

Part one uses the web client login form with the special parameter sessionId to connect the request to the session we created earlier. This makes it simple for us to reuse this session just by passing around the session id which is a GUID stored as a simple string.

Part two is the actual document link. We use the second special parameter originalUrl to tell LoginForm.aspx to go to the document link after the session id has been assigned. The document link points to the web client viewer form. When there is no web viewer licensed or assigned for the file type the document will simply download to the requestor. The docId parameter is used to specify the FileHold id for the document. This form of request always accesses the most current version that the logged in user has permission for.

Since the originalUrl is parameter in an url and taking another url as its value, we need some special magic for that second url. This is to avoid characters in the second url that conflict with the processing of the first url. For example, the slash “/” is a reserved character in the url. Since the value of originalUrl contains slashes we need to escape them so they cannot be interpreted until the time is right. This is what the UrlEncode method does for us.

$documentAddress = $fileHoldUrl + "/WebClient/LoginForm.aspx?sessionId=" + $sessionId + "&originalUrl=" +
      [System.Web.HttpUtility]::UrlEncode( $fileHoldUrl + "/WebClient/ViewerForm.aspx?docId=" + $fileHoldId )
$progressPreference = 'silentlyContinue'
Invoke-WebRequest $documentAddress -outfile $tempFile

Well, that is it. A link to the complete cmdlet is included at the bottom of the page. This cmdlet can now be called from a command line as we describe at the top of the article. In addition to dealing with passwords in a good way, the sample script described here could be improved for production use with some error checking. For example, what if we cannot create a session in FileHold? What if the server address is wrong?

You can learn more about the various FileHold features used in this article at the following links. If you would like help creating scripts like this for your FileHold installation you can contact the FileHold professional and consulting services team at support@filehold.com for assistance.





The FileHold API is included with every FileHold license, but unlimited FileCare support is not included. Also, you should be aware of the terms of use for the API.


If you are looking for an automated way to find the FileHold id you might want to check out this link.


The full sample script.


profile picture russ beinder Russ Beinder is the Chief Technology Officer at FileHold. He is an entrepreneur, a seasoned business analyst, computer technologist and a certified Project Management Professional (PMP). For the last 25 years he has used computer technology to help organizations solve business problems.