2/20/2014

Download a File from SharePoint using PowerShell

 

I recently had a request for a PowerShell script that could be run as a Windows scheduled task to download a file each night to a network share. As is typical, there's more than one way…

 

The PowerShell / .Net approach:

This is a ".Net approach" as it does not use any PowerShell cmdlets (beyond New-Object). The following will work from all versions of PowerShell and SharePoint 2007 – 2013, but not Office 365. It will work from any client PC as long as you have permissions to access the file. Why not Office 365? O365 requires an authentication cookie. (When I get some time I'll post an O365 version.)

$fromfile = "http://yourserver/sites/yoursite/shared%20documents/yourfile.xlsx"
$tofile   = "c:\somedirectory\yourfile.xlsx"

$webclient = New-Object System.Net.WebClient

$webclient.UseDefaultCredentials = $true
#  or
# $webclient.Credentials = …
$webclient.DownloadFile($fromfile, $tofile)

 

The SharePoint Approach:

This approach must be run from a SharePoint server and uses the Get-SPWeb cmdlet to access a site. As it is much more complicated, why would you ever use it? To do more complex things! Things like getting all of the files from a library and then downloading them (in a foreach loop), ZIPing the file(s) before download or otherwise manipulating the files before download.

The following will work from the SharePoint 2010 and 2013 Management Shells (but not for Office 365). Why not Office 365? The following needs to be run on the SharePoint server, and you are not allowed to do that with O365.

$fromsite = "http://yourserver/sites/yoursite"

$fromfile = "yourlibrary/yourfile.xlsx"
$tofile   = "c:\test\yourfile.xlsx"

$web = Get-SPWeb $fromsite
$file = $web.GetFile($fromfile)
$filebytes = $file.OpenBinary()

$filestream = New-Object System.IO.FileStream($tofile, "Create")
$binarywriter = New-Object System.IO.BinaryWriter($filestream)
$binarywriter.write($filebytes)
$binarywriter.Close()

 

.

12 comments:

Anonymous said...

Hi Mike,

Have you found a solution around the O365 problem yet? I have not seen any other guides which present a solution to download a single file form an O365 ShraePoint site. Help me Mike, you're my only hope!

Mike Smith said...


Anonymous,

The following uses SharePoint's CSOM, so you must have both Microsoft.SharePoint.Client.dll and Microsoft.SharePoint.Client.Runtime.dll on your PC.

I'll see if I can put together a more complete article on using CSOM for downloads.



# requires the 64 bit version of PowerShell or the ISE

$siteUrl = "https://microsmith.sharepoint.com"
$library = "Class Documents"
$listItemId = 24 #item's list ID

$toPath = "c:\xfer\" #yourfile.xlsx"

$username = "mike@somesite.onmicrosoft.com"
$password = Read-Host -Prompt "Password for $username" -AsSecureString


$clientContext = [Microsoft.SharePoint.Client.ClientContext,Microsoft.SharePoint.Client, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c]


$context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)

$context.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username,$password)
$web = $context.Web
$context.Load($web)
$context.ExecuteQuery()

$list = $context.Web.Lists.GetByTitle($library);
$listitem = $list.GetItemById($listItemId);
$context.Load($list);
$file=$listItem.File
$context.Load($file);
$context.ExecuteQuery()


$fileRef = $file.ServerRelativeUrl;
$fileInfo = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($context, $fileRef);
$fileName = $toPath + $File.Name
$fileStream = [System.IO.File]::Create($fileName)
$fileInfo.Stream.CopyTo($fileStream);

$fileStream.Close()


Mike

Anonymous said...

thank you

Anonymous said...

Good day guys.
Is it possible to do the same script only for uploading?
So I have a task, some xlsx files store on C drive and need to upload all of them to SharePoint site? How to do that?

Thank you
Alexandr

Mike Smith said...

Alexandr,

Here's an upload script:

# Set a few variables
$file = "C:\test\myTestFile.txt"
$webUrl = "http://server/sites/yoursite"
$library = "Team Documents"
$overWriteExisting = $True #or add new version if versioning enabled

# do a little SharePoint setup
$web = Get-SPWeb $webUrl
$files = $web.GetFolder($library).Files
$fileNameForLibrary = $file.Substring($file.LastIndexOf("\")+1)

# read the file
$data = Get-ChildItem $file

# add any needed metadata
$metadata = @{ "Project ID" = "A-200"; "Region" = "North" }

# or if no metadata needed: $metadata = @{}

# do the upload (the following is one line)
$newfile = $files.Add($library + "/" + $fileNameForLibrary, $data.OpenRead(), $metadata, $overWriteExisting)

Mike

Anonymous said...

Hi Mike,

I'm very interested in using this script for my project. I'm unfamiliar with using PowerShell and I'm not sure of the exact steps to get this running.

I've tried saving the exact code as a .ps1 file then running it as a task, but the code then opens up in Notepad. Am I missing a step somewhere in here? Do I need to include anything in the "Arguments" or "Start In" sections of the task actions?

Thanks in advance for all your help

Anonymous said...

To be more specific to my post above (July 14, 2015 at 5:58 PM), I've tried running the code and I get the following error:

Exception calling "DownloadFile" with "2" argument(s): "An exception occurred during a WebClient request."
At C:\Users\****\Desktop\Test.ps1:9 char:24
+ $webclient.DownloadFile <<<< ($fromfile, $tofile)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException


Not too sure what this means; I do have permissions to the SharePoint site.

Mike Smith said...

Anonymous,

You will need some PowerShell experience, if not now, in the future! That said...

There are several ways of running PowerShell as a scheduled job:
- Using PowerShell's job scheduling features.
- Using a Windows task.
- Using a SQL Server Agent Job.

This may not be easy without some PowerShell experience depending on where you are running the job, and the permissions needed to perform the task.



If you want run the PowerShell on the SharePoint server using PowerShell jobs then see: http://blogs.technet.com/b/heyscriptingguy/archive/2012/09/18/create-a-powershell-scheduled-job.aspx

As a Windows Scheduled task: http://www.metalogix.com/help/Content%20Matrix%20Console/SharePoint%20Edition/002_HowTo/004_SharePointActions/012_SchedulingPowerShell.htm

As a SQL Agent Job: https://technet.microsoft.com/en-us/library/hh213688(v=sql.110).aspx



or do a web search for "run powershell as a job"

Mike Smith said...

The error message implies that either $fromfile is not a valid URL to the document or $tofile is not a valid path/filename.

Anonymous said...

The vanilla .net approach saved my day, i have spent so much time trying to figure out how to download with curl and wget for windows without success.

Anonymous said...

Hi Mike,

when you say "The following uses SharePoint's CSOM, so you must have both Microsoft.SharePoint.Client.dll and Microsoft.SharePoint.Client.Runtime.dll on your PC."

Can these dlls be installed by downloading and installing the SharePoint Online Client Components SDK located here:
https://www.microsoft.com/en-ca/download/details.aspx?id=42038

If not, how can I get ahold of these dlls?

Thank you!

Mike Smith said...

> Can these dlls be installed by downloading and installing the SharePoint Online Client Components SDK

Use can also use the links and instructions found here: https://social.technet.microsoft.com/wiki/contents/articles/29518.csom-sharepoint-powershell-reference-and-example-codes.aspx

Note to spammers!

Spammers, don't waste your time... all posts are moderated. If your comment includes unrelated links, is advertising, or just pure spam, it will never be seen.