0

I am trying to download a file with PowerShell from a SharePoint online site.

I have tried the script provided here: SharePoint Online: Download a File from Library using PowerShell.

But without any luck. The script manages to produce an output file that is corrupted.

Does anyone have a script working with Windows 10, SharePoint and office 2016?

Thanks in advance.

2

You can use this cmdlet : Get-PnPFile

Get-PnPFile -Url fileUrl -AsFile
| improve this answer | |
0

Here is a complete working PowerShell script using that we can download files from SharePoint online document library:

#Load SharePoint CSOM Assemblies
#Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
#Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
cls

$fileName = "File_Downloading_Report"
#'yyyyMMddhhmm   yyyyMMdd
$enddate = (Get-Date).tostring("yyyyMMddhhmmss")
#$filename =  $enddate + '_VMReport.doc'  
$logFileName = $fileName +"_"+ $enddate+"_Log.txt"   
$invocation = (Get-Variable MyInvocation).Value  
$directoryPath = Split-Path $invocation.MyCommand.Path  

$directoryPathForLog=$directoryPath+"\"+"LogFiles"
if(!(Test-Path -path $directoryPathForLog))  
        {  
            New-Item -ItemType directory -Path $directoryPathForLog
            #Write-Host "Please Provide Proper Log Path" -ForegroundColor Red   
        }  


#$logPath = $directoryPath + "\" + $logFileName 

$logPath = $directoryPathForLog + "\" + $logFileName 

$isLogFileCreated = $False 

#DLL location

$directoryPathForDLL=$directoryPath+"\"+"Dependency Files"
if(!(Test-Path -path $directoryPathForDLL))  
        {  
            New-Item -ItemType directory -Path $directoryPathForDLL
            #Write-Host "Please Provide Proper Log Path" -ForegroundColor Red   
        } 

#DLL location
$clientDLL=$directoryPathForDLL+"\"+"Microsoft.SharePoint.Client.dll"
$clientDLLRuntime=$directoryPathForDLL+"\"+"Microsoft.SharePoint.Client.dll"

Add-Type -Path $clientDLL
Add-Type -Path $clientDLLRuntime
#File Download location

$directoryPathForFileDownloadLocation=$directoryPath+"\"+"Downloaded Files"
if(!(Test-Path -path $directoryPathForFileDownloadLocation))  
        {  
            New-Item -ItemType directory -Path $directoryPathForFileDownloadLocation
            #Write-Host "Please Provide Proper Log Path" -ForegroundColor Red   
        } 

#File Download location



function Write-Log([string]$logMsg)  
{   
    if(!$isLogFileCreated){   
        Write-Host "Creating Log File..."   
        if(!(Test-Path -path $directoryPath))  
        {  
            Write-Host "Please Provide Proper Log Path" -ForegroundColor Red   
        }   
        else   
        {   
            $script:isLogFileCreated = $True   
            Write-Host "Log File ($logFileName) Created..."   
            [string]$logMessage = [System.String]::Format("[$(Get-Date)] - {0}", $logMsg)   
            Add-Content -Path $logPath -Value $logMessage   
        }   
    }   
    else   
    {   
        [string]$logMessage = [System.String]::Format("[$(Get-Date)] - {0}", $logMsg)   
        Add-Content -Path $logPath -Value $logMessage   
    }   
} 



#The below function will download the file from SharePoint Online library.
Function FileDownLoadFromSPOnlineLibrary()
{
    param
    (
        [Parameter(Mandatory=$true)] [string] $SPOSiteURL,
        [Parameter(Mandatory=$true)] [string] $SourceFilePath,
        [Parameter(Mandatory=$true)] [string] $TargetFilePath,
        [Parameter(Mandatory=$true)] [string] $UserName,
        [Parameter(Mandatory=$true)] [string] $Password
    )

    Try 
    {      

        $securePassword= $Password | ConvertTo-SecureString -AsPlainText -Force  
        #Setup the Context
        $ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SPOSiteURL)
        $ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName, $securePassword)

        #Downloading the file from SharePoint online document libray.
        $fileInfo = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($ctx,$SourceFilePath)
        $writeStream = [System.IO.File]::Open($TargetFilePath,[System.IO.FileMode]::Create)
        $fileInfo.Stream.CopyTo($writeStream)
        $writeStream.Close()

        Write-host -f Green "File '$SourceFilePath' has been downloaded to '$TargetFilePath' successfully!"
    }
    Catch 
    {

            $ErrorMessage = $_.Exception.Message +"in Downloading File!: " +$SourceFilePath
            Write-Host $ErrorMessage -BackgroundColor Red
            Write-Log $ErrorMessage 

    }
}


#Parameters value
$siteURL="https://globalsharepoint.sharepoint.com/sites/TestSite/"
$listName="Documents" #Document library name
$fromDate="2019-10-28"
$toDate="2019-11-09"
$downloadLocation=$directoryPathForFileDownloadLocation;
$userName = "YourSPOAccount@YourTenantDomain.com"
$password = "YourPassWord"
$securePassword= $password | ConvertTo-SecureString -AsPlainText -Force
#$batchSize =1000
#Parameters ends here.



#Setup the Context
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteURL)
$ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($userName, $securePassword)

#Get the List
$list = $ctx.Web.Lists.GetByTitle($listName)
$ctx.Load($list)
$ctx.ExecuteQuery()
$emptyString = ""
#Define CAML Query to get Files from the list in batches
$Query = New-Object Microsoft.SharePoint.Client.CamlQuery

#Here in the below two-line "T13:35:58Z" and "T13:36:34Z" are hardcoded static value - because while we construct this camel query through the camel query builder these values get appended to the date value, so we need this.
$startDateVar=$fromDate+"T13:35:58Z"  
$endDateVar=$toDate+"T13:36:34Z"
#Here in the below two-line "T13:35:58Z" and "T13:36:34Z" are hardcoded static value - ends here.
#RecursiveAll


$Query.ViewXml = "@
    <View Scope='RecursiveAll'>
        <Query>
   <Where>
      <And>
         <Geq>
            <FieldRef Name='Created' />
            <Value IncludeTimeValue='TRUE' Type='DateTime'>$startDateVar</Value>
         </Geq>
         <Leq>
            <FieldRef Name='Created' />
            <Value IncludeTimeValue='TRUE' Type='DateTime'>$endDateVar</Value>
         </Leq>
      </And>
   </Where>
</Query>        
    </View>"


$count =0
#Get List Items in Batches
Do
{


    $ListItems = $List.GetItems($Query)
    $Ctx.Load($ListItems)
    $Ctx.ExecuteQuery()
    $ListItems.Count

    #Update Postion of the ListItemCollectionPosition
    $Query.ListItemCollectionPosition = $ListItems.ListItemCollectionPosition
    $Query.ListItemCollectionPosition

    If ($ListItems.Count -eq 0) 
    { 
    Break
    }

    $downloadItemCount=1;

    #Extract the each list item from the List Items collection.
    ForEach($Item in $ListItems)
    {                  
          #Example to Item metadata - this can be used if we want to download based on some item metadata condition.
          #$documentStatus=$Item["documentStatusColumnName"]

            try
            {

                $Ctx.Load($Item.File)
                $Ctx.ExecuteQuery()
                #$eTagVal=$Item.File.ETag                                         

                #https://globalsharepoint.sharepoint.com/sites/TestSite/Shared%20Documents/LegalDoc.docx        
                $SourceFile=$Item.File.ServerRelativeUrl;
                #$TargetFile="C:\PowerShell\DownLoadFilesFromSPOnline\Downloaded Files\LegalDoc.docx" 
                $TargetFile=$downloadLocation+"\"+$Item.File.Name; 

                #If we want to download the specific file type we can check the file type using the below code 
                #if($SourceFile.Contains(".zip")){}

                #Calling the function "FileDownLoadFromSPOnlineLibrary"to download file
                FileDownLoadFromSPOnlineLibrary -SPOSiteURL $SiteURL -SourceFilePath $SourceFile -TargetFilePath $TargetFile -UserName $UserName -Password $Password

                $fileDownloadingMessage=$downloadItemCount.ToString()+": "+$Item.File.Name; 
                Write-Host $fileDownloadingMessage -BackgroundColor DarkGreen
                Write-Log $fileDownloadingMessage

        $downloadItemCount++

        }
        catch
        { 
            $ErrorMessage = $_.Exception.Message +"in: " +$Item.File.Name
            Write-Host $ErrorMessage -BackgroundColor Red
            Write-Log $ErrorMessage 

        }

    }
    Write-Host "============================================================="
    Write-Host $count
    Write-Host "============================================================="

}While ($Query.ListItemCollectionPosition -ne $null)

For details steps of execution, please refer the below article :

SharePoint Online Automation – O365 – Download files from a document library using PowerShell CSOM

| improve this answer | |
0

I tested with the following script and works in my win 10 with SharePoint Online site. Have a try and update with any errors when using all the scripts provided by us.

#Config Variables
$SiteURL = "https://domain.sharepoint.com/sites/TeamSite1"
$FileRelativeURL = "/sites/TeamSite1/Shared Documents/PermissionRpt.csv"
$DownloadPath ="C:\temp"

#Get Credentials to connect
$Cred = Get-Credential

Try {
    #Connect to PNP Online
    Connect-PnPOnline -Url $SiteURL -Credentials $Cred

    #powershell download file from sharepoint online
    Get-PnPFile -Url $FileRelativeURL -Path $DownloadPath -AsFile
}
catch {
    write-host "Error: $($_.Exception.Message)" -foregroundcolor Red
}
| improve this answer | |
  • And when you open the downloaded file, it is not corrupted? The sharepoint site is technically a teams site, will this have an impact? – hfarbrot Mar 10 at 7:49
  • @hfarbrot I tested with PNG csv and docx files and they seems to be fine and opened without problem. Team site is totally fine with the script. I am testing with a team site. – Jerry_MSFT Mar 10 at 9:06
  • thank you, got it working finally – hfarbrot Mar 10 at 11:39
  • @hfarbrot Glad to hear you finally get it done. You can accept the helpful reply as answer. – Jerry_MSFT Mar 12 at 1:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.