Копирование (синхронизация) файлов из SharePoint в локальную папку

Копирование (синхронизация) файлов из SharePoint в локальную папку

В одном из клиентских сценариев понадобилось настроить автоматическое копирование файлов и папок из библиотеки SharePoint Online в каталог на локальном файловом сервере.

Предпочтительным способом синхронизации файлов из библиотеки SharePoint Online является использования клиента OneDrive (OneDrive позволяет синхронизировать файлы из указанной библиотеки SharePoint), однако это требует наличия активной сессии пользователя Microsoft 365 и лицензии для пользователя. В этой статье мы рассмотрим PowerShell скрипт для копирования (синхронизации) файлов из библиотеки SharePoint в локальной хранилище на on-premises Windows Server.

Задание копирования файлов из SharePoint Online должно запускаться автоматически из планировщика на одном из хостов Windows Server. Для этого нужно:

  1. Создать в Azure (Entra ID) отдельное приложение (App registration);
  2. Предоставить приложению следующие права: Microsoft Graph (
    Files.Read.All
    и
    User.Read
    ) и SharePoint (
    Sites.FullControl.All
    ,
    User.Read.All
    ,
    Sites.Read.All
    ,
    Sites.Selected
    и
    TermStore.Read.All
    );
    Порядок регистрации приложения в Azure для доступа через Microsoft Graph API описан здесь.
  3. Создать сертификат для аутентификации в приложении Azure из скрипта PowerShell без пароля;
  4. Установить PowerShell Core на компьютере, который будет запускать скрипт копирования файлов.

Создайте переменные для скрипта и подставьте в них свои данные:

$certThumbprint = "7E82C3A560737C7894562593926E495777ECDB75"
$AzureAppID = "123456-1234-1234-1234-123456789"
$tenant="winitpro.onmicrosoft.com"

Параметры сайта и библиотеки SharePoint, файлы из которой вы будете копировать:

$siteUrl = "https://winitpro.sharepoint.com/sites/SyncLibrary"
$LibraryFolder = "/Shared Documents/General"

Путь к целевой локальной папке, в которую нужно копировать файлы:

$localFolderPath = "fs01DocsSharePoint"

Путь к файлу лога:

$Logfile = $localFolderPath + "sharepoint_sync_sync.log"

Создайте PowerShell функцию, которая будет писать лог:

function WriteLog
{
    Param ([string]$LogString)
    $Stamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss")
    $LogMessage = "$Stamp $LogString"
    Add-content $LogFile -value $LogMessage
}
WriteLog "Script started....."

Для подключения к SharePoint Online нужно установить модуль PnP:

Install-Module PnP.PowerShell

Подключитесь к SharePoint Online с помощью команду:

Connect-PnPOnline -Url $siteUrl -ApplicationId $AzureAppID -Tenant $tenant -Thumbprint $certThumbprint

Следующий этап необходимы для корректной синхронизации. Нужно удалить в локальном хранилище файлы, которые были ранее удалены на сайте SharePoint (проверяется наличие файлы в корзине SPO):

$removedobjects= Get-PnPRecycleBinItem|select Title, DirName ,ItemType,DeletedDate 
    foreach ($removedobject in $removedobjects) {
        $removedpath= $removedobject.DirName -replace 'sites/winitpro/Shared Documents/General', ''
        $removedpath =   $removedpath -replace '/', ''
        $removedpath =  $localFolderPath + $removedpath + "" + $removedobject.Title
         If (Test-Path -Path $removedpath) {
                   WriteLog "Object exists, need to delete: $removedpath"                       
                   Remove-Item -Path $removedpath   -Recurse -Force
          }
    }

Получить все объекты (файлы и папки в библиотеке SharePoint):

$files= Get-PnPFolderItem -FolderSiteRelativeUrl $LibraryFolder -Connection $Connection -Recursive|select Name,ServerRelativeUrl,TimeLastModified,TypedObject

Затем в цикле выполняется перебор всех полученных объектов. Если это папка, и она отсутствует в целевом каталоге, она будет создана. Затем скрипт копирует новые файлы из SharePoint в локальную папку:

foreach ($file in $files) {
     #create new folders
     if ($file.TypedObject -like "*Folder*")
        {
             $NewLocalFolder = $file.ServerRelativeUrl -replace '^/sites/winitpro/Shared Documents/General', ''
  $NewLocalFolder =  $NewLocalFolder -replace '/', ''
             $NewLocalFolder =  $localFolderPath + $NewLocalFolder
                If (!(Test-Path -Path $NewLocalFolder)) {
                        WriteLog "Create folder: $NewLocalFolder"
                        New-Item -ItemType Directory -Path $NewLocalFolder | Out-Null
                    }
            else {
           }
        }   
    # copy new files 
    if ($file.TypedObject -like "*File*") {
        $localfolder= $file.ServerRelativeUrl -replace '^/sites/winitpro/Shared Documents/General', ''
        $lastSlashIndex = $localfolder.LastIndexOf("/")
        $localfolder = ($localfolder.Substring(0, $lastSlashIndex)) -replace '/', ''
        $localfolder = $localFolderPath + $localfolder
        $localFileName = $localfolder + "" + $file.Name
        $localFileExists = Test-Path -Path ( $localFileName)
        if (!$localFileExists) {
                WriteLog "Copy New Files: $file.ServerRelativeUrl to  $localFileName   $file.TypedObject"
                Get-PnPFile -Url $file.ServerRelativeUrl -Path  $localfolder -FileName $file.Name -AsFile
            }
            else {
            $localFileNameLastWrite = (Get-Item  $localFileName).LastWriteTime
            if ($localFileNameLastWrite -lt $file.TimeLastModified) {
                WriteLog "Copy changed files: $localFileNameLastWrite vs  $file.TimeLastModified   file: $file.name"
                Get-PnPFile -Url $file.ServerRelativeUrl -Path  $localfolder -FileName $file.Name -AsFile -Force
            } 
        } 
    }
}

После этого нужно отключиться от SharePoint:

Disconnect-PnPOnline
WriteLog "Script finished....."

Этот PowerShell скрипт можно запускать из планировщика Windows с необходимой вам периодичностью (первичная синхронизация может занять длительное время, зависящее от размер библиотеки SharePoint).

Создайте задание планировщика с именем SyncFilesfromSharepointOnline. Задание должно запускать от имени SYSTEM.

Задание планировщика SyncFilesfromSharepointOnline

В настройках задания указать программу
"C:Program FilesPowerShell7pwsh.exe"
с параметром
-Noprofile -WindowStyle Hidden -ExecutionPolicy Bypass -File C:PSsharepoint_syncscript.ps1

Запуск скрипта синхронизации SharePoint библиотеки в локальную папку

Таким образом мы настроили автоматическое копирование (синхронизацию) файлов из библиотеки SharePoint в локальную папку.

PowerShell
Копирование (синхронизация) файлов из SharePoint в локальную папку