Поиск по сайту:

Как архивировать SharePoint Online?


SharePoint Online — это отличный инструмент для хранения и обмена файлами, совместной работы над проектами и общения с членами команды. Однако по мере увеличения объема данных, хранящихся в SharePoint Online, вы, вероятно, столкнетесь с нехваткой места для хранения.

Вы можете купить дополнительное хранилище в SharePoint Online, что может стать довольно дорогим. Другим вариантом было бы архивировать старые сайты SharePoint, но какие у вас есть варианты для этого?

В этой статье мы рассмотрим различные варианты архивирования SharePoint. Включая передачу данных на локальное хранилище (например, NAS), облачное хранилище Azure и мы также оценим новые функции Microsoft Sentex, которые будут доступны в будущем.

Архивирование SharePoint

Несмотря на то, что SharePoint Online предоставляет большое количество места для хранения, с течением времени вы увидите, что многие организации исчерпывают его, по мере роста компании. Одной из причин этого является версияция, которая выполняется по умолчанию в SharePoint Online. SharePoint сохраняет до 500 копий (версий) файла. В зависимости от типа и размера файла это может занять много места для хранения.

Заметка

Узнайте больше о хранилище SharePoint Online в этой статье.

Можно купить дополнительное хранилище, но при цене $0,20 за ГБ в месяц счет может быстро увеличиться. Поэтому многие компании рассматривают возможность архивации SharePoint Online.

Microsoft выпустила Microsoft 365 Archive, он все еще находится в режиме предварительного просмотра, но вы уже можете его протестировать. Другие варианты архивирования ваших сайтов SharePoint:

  • Скачайте данные на локальное устройство хранения
  • Переместите данные в Azure blob
  • Используйте решение для резервного копирования от третьей стороны

Существует еще два варианта, о которых часто упоминают при поиске решений для архивирования в SharePoint. Установка политик хранения — один из них, но, на мой взгляд, это не является архивированием. Политика хранения просто удалит файлы, которые не использовались более года, например.

Другой вариант - перенести данные в учетную запись OneDrive выделенного пользователя. OneDrive предоставляет вам 5 ТБ хранилища, так что это может быть вариантом для некоторых. Но помните, что OneDrive не предназначен для легкого доступа многими пользователями и это также может противоречить Соглашению об услугах Microsoft.

Архивировать SharePoint на локальное хранилище (NAS)

Перемещение данных на локальное хранилище, например, NAS, часто является хорошим и доступным решением для архивирования SharePoint. Преимущество локального хранилища заключается в том, что оно требует только одноразовых инвестиций каждые 5-7 лет и его легко расширить.

Но у этого также есть и обратная сторона, о которой часто забывают. Если вы разместите NAS в своем офисе с архивированными данными SharePoint, убедитесь, что у вас также есть резервная копия этого хранилища. Вы не будете первым, у кого NAS выйдет из строя, и вы потеряете все данные.

Совет

Лично я использую Synology RS822+ в качестве основного NAS и меньшую DS220+ в качестве резервной копии RS822+.

В современных библиотеках SharePoint вы можете просто выбрать все файлы в документной библиотеке и нажать кнопку загрузки, чтобы скачать все файлы. Однако вам придется делать это для каждой документной библиотеки, но это самый простой способ архивировать файлы в другое решение для хранения.

Если вам нужно архивировать много файлов и библиотек документов, то лучшее решение - использовать для этого скрипт PowerShell. Ниже приведен скрипт, который загрузит все библиотеки документов с указанного сайта SharePoint и скачает файлы в указанную папку. Он основан на скрипте с SharePointDairy.com, но я расширил его, добавив исключения и ведение журнала.

Список исключений, определенный в функции Get-DocLibraries, фильтрует страницы сайта, ресурсы, библиотеки с удержанием сохранности и другие, которые нам не нужны. Вы можете получить последнюю версию скрипта здесь из моего репозитория на GitHub.

Статья продолжается ниже текста

<#
.Synopsis
  Download all libaries, folders and files from SPO.

.DESCRIPTION
  Script is based on https://www.sharepointdiary.com/2017/07/download-all-files-from-sharepoint-site.html from Salaudeen.

  Script copies all document libraries including all content from SharePoint Online (SPO) to a local folder. Logging is 
  done through a log file, path for log file can be set.

  You can re-run the script, it will check if local files exists. If the file on SPO is newer, then it will update the local file.

  Scripts counts the number of files copied and skipped.

.NOTES
  Name: Copy-SpSiteToNAS.ps1
  Author: R. Mens
          S. Rajack
  Version: 1.1
  DateCreated:  2022
  Purpose/Change: init

.LINK
  a-d.site

[CmdletBinding(DefaultParameterSetName="Default")]
param(
  [Parameter(
    Mandatory = $true,
    HelpMessage = "SharePoint Site Url"
    )]
  [string]$siteUrl,

  [Parameter(
    Mandatory = $true,
    HelpMessage = "Enter path where to download files to"
    )]
  [string]$downloadPath,

  [Parameter(
    Mandatory = $false,
    HelpMessage = "Enter path for log file location"
    )]
  [string]$logFilePath = "c:\temp\sp-archive.txt",

  [Parameter(
    Mandatory = $false,
    HelpMessage = "Set log level"
  )]
  [ValidateSet("error", "warn", "info", "full")]
  [string]$logLevel = "full"
)
Init Log file
$Global:logFile = [string]""
$Global:filesCopied = [int] 0
$Global:filesSkipped = [int] 0

Function Write-Log {
  <#
    .SYNOPSIS
    Save output in log file
  #>
  param(
      [Parameter(Mandatory = $true)][string] $message,
      [Parameter(Mandatory = $false)]
      [ValidateSet("FULL","INFO","WARN","ERROR")]
      [string] $level = "INFO"
  )
  
  # Create timestamp
  $timestamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss")

  if ($logLevel -eq 'warn') {
    $allowedLevels = @(
      'warn',
      'error'
    )
  }elseif ($loglevel -eq 'info') {
    $allowedLevels = @(
      'info',
      'warn',
      'error'
    )
  }elseif ($loglevel -eq 'full') {
    $allowedLevels = @(
      'full',
      'info',
      'warn',
      'error'
    )
  }
  # Output errors also to console
  if ($allowedLevels -contains $level) {
    # Append content to log file
    Add-Content -Path $Global:logFile -Value "$timestamp [$level] - $message"
  }

  # Output errors also to console
  if ($level -eq 'ERROR') {
    Write-host $message -ForegroundColor red
  }
}

Function Get-DocLibraries {
  <#
    .SYNOPSIS
    Get all document libraries from the SharePoint site, except excluded ones
  #>

  #Excluded libraries
  $ExcludedLists = @(
    "FormServerTemplates", 
    "Images",
    "Pages", 
    "PreservationHoldlibrary",
    "SiteAssets", 
    "SitePages", 
    "Style_x0020_library"
  )

  Get-PnPList -Includes RootFolder | Where-Object {$_.BaseType -eq "Documentlibrary" -and $_.EntityTypeName -notin $ExcludedLists -and $_.Hidden -eq $False}
}

Function Get-SPOFiles {
  <#
  .SYNOPSIS
    List all folders and files from the given library
  #>
  param(
    [Parameter(Mandatory = $true)] $List
  )
  process{
    Try {
      # Get all Items from the library - with progress bar
      $global:itemCounter = 0

      Get-PnPListItem -List $List -PageSize 1000 -Fields ID -ScriptBlock { 
        Param($items) 
        $global:itemCounter += $items.Count;

        # Create progress bar
        $getItemsProgress = @{
          Activity         = "Get items from $($List.Title)"
          Status           = "Progress->"
          PercentComplete  = ($global:itemCounter/$list.itemCount) * 100
          CurrentOperation = "$($items.Count) of $($list.itemCount)"
        }
        Write-Progress @getItemsProgress
      } 
       
      Write-Progress -Activity "Completed gettings items from library $($List.Title)" -Completed
    }Catch{
      Write-Log -Message "Error Downloading library $($List.Title) : $($_.Exception.Message)" -level ERROR
    }
  }
}

Function Copy-SPOFiles(){
  <#
  .SYNOPSIS
    Download all folders and files from the given library
  #>
  param(
    [Parameter(Mandatory = $true)] $ListItems,
    [Parameter(Mandatory = $true)] $List,
    [Parameter(Mandatory = $true)] $localFolder
  )
  process{
    Try {
      # Create a Local Folder for the Document library, if it doesn't exist
      $libraryFolder = $localFolder +"\" +$List.RootFolder.Name

      If (!(Test-Path -Path $libraryFolder)) {
        New-Item -ItemType Directory -Path $libraryFolder | Out-Null
      }

      # Get all Subfolders of the library
      $SubFolders = $ListItems | Where {$_.FileSystemObjectType -eq "Folder" -and $_.FieldValues.FileLeafRef -ne "Forms"}
      $SubFolders | ForEach-Object {
          # Create local path for the sub folder
          $LocalFolderPath = $localFolder + ($_.FieldValues.FileRef.Substring($Web.ServerRelativeUrl.Length)) -replace "/","\"
          
          # Create Local Folder, if it doesn't exist
          If (!(Test-Path -Path $LocalFolderPath)) {
                  New-Item -ItemType Directory -Path $LocalFolderPath | Out-Null
          }
          Write-Log -Message "Created subfolder $LocalFolderPath" -level FULL
      }

      # Get all Files from the folder
      $FilesColl =  $ListItems | Where {$_.FileSystemObjectType -eq "File"}
      $FileCounter = 0

      # Iterate through each file and download
      $FilesColl | ForEach-Object {

          # Frame the Parameters to download file
          $FileDownloadPath = ($localFolder + ($_.FieldValues.FileRef.Substring($Web.ServerRelativeUrl.Length)) -replace "/","\").Replace($_.FieldValues.FileLeafRef,'')
          
          $FileName = $_.FieldValues.FileLeafRef
          $SourceURL = $_.FieldValues.FileRef
          $FileModifiedDate = $_.FieldValues.Modified

          # Creating progressbar
          $FileCounter += 1;

          $downloadItemsProgress = @{
            Activity         = "Downloading items from $($List.Title)"
            Status           = "Progress->"
            PercentComplete  = ($FileCounter/$FilesColl.Count) * 100
            CurrentOperation = $FileName
          }
          Write-Progress @downloadItemsProgress

          #Check File Exists
          $FilePath = Join-Path -Path $FileDownloadPath -ChildPath $_.FieldValues.FileLeafRef

          If (-not(Test-Path -Path $FilePath -PathType Leaf)) {
            # Download the File
            Get-PnPFile -ServerRelativeUrl $SourceURL -Path $FileDownloadPath -FileName $FileName -AsFile -force
            Write-Log -Message "Downloaded $FileName from $SourceUrl " -level FULL
            $Global:filesCopied++
          }else{
            # Compare local and SPO file date
            if ($FileModifiedDate -gt ( Get-ChildItem -Path $FilePath | Select -ExpandProperty LastWriteTime)) {
              # SPO file is newer than local file, overwrite local file
              Get-PnPFile -ServerRelativeUrl $SourceURL -Path $FileDownloadPath -FileName $FileName -AsFile -force
              Write-Log -Message "Downloaded newer version of $FileName from $SourceUrl " -level FULL
              $Global:filesCopied++
            }else{
              Write-Log -Message "Skipped $FileName from $SourceUrl - Already exists" -level FULL
              $Global:filesSkipped++
            }
          }
      }
      Write-Progress -CurrentOperation "downloadItems" -Activity "Completed downloading items from library $($List.Title)" -Completed
    }
    Catch {
      Write-Log -Message "Error Downloading library $($List.Title) : $($_.Exception.Message)" -level ERROR
    }
  }
}

Function Get-NrOfDownloadedFiles() {
  <#
  .SYNOPSIS
    Download all folders and files from the given library
  #>
  param(
    [Parameter(Mandatory = $true)] $localFolder,
    [Parameter(Mandatory = $true)] $List
  )
  Process {
    $libraryFolder = $localFolder +"\" +$List.RootFolder.Name

    If (Test-Path -Path $libraryFolder) {
      (Get-ChildItem -Path $libraryFolder -File -Recurse).count
    }
  }
}

Function New-SPSiteArchiveFolder() {
  <#
  .SYNOPSIS
    Download all folders and files from the given library
  #>
  param(
    [Parameter(Mandatory = $true)] $title,
    [Parameter(Mandatory = $true)] $downloadPath
  )
  process {
    If (!(Test-Path -Path ($downloadPath +"\" +$title))) {
      New-Item -Path $downloadPath -Name $title -ItemType 'directory'
    }Else{
      $downloadPath +"\" +$title
    }
  }
}

Connect to SharePoint Online
Connect-PnPOnline $SiteURL -Interactive
$Web = Get-PnPWeb
 
Create Log file
$Global:logFile = $logFilePath + "\" + $Web.title + ".txt"
New-Item -Path $Global:logFile -Force | Out-Null

Create folder for SharePoint site in Archive folder
$localFolder = New-SPSiteArchiveFolder -DownloadPath $downloadPath -title $web.title

Get all the libraries
$documentLibraries = Get-DocLibraries
Write-Log -Message  "$(($documentLibraries).count) Document Libraries found" -level INFO

Download all the files from each library if they contain items
ForEach($library in $documentLibraries)
{
  if ($library.itemCount -ne 0) {
    Write-Log -Message "Process document library : $($library.title)" -level INFO
    
    # Count nr of files in the doc library
    $SPOItems = Get-SPOFiles -List $library
    Write-Log -Message "$($SPOItems.count) files and folders found in $($library.title)" -level INFO
    
    # Download the files
    Copy-SPOFiles -List $library -ListItems $SPOItems -localFolder $localFolder

    # Count files in the local folder
    $CountLocalItems = Get-NrOfDownloadedFiles -List $library -localFolder $localFolder
    Write-Log -Message "$CountLocalItems files downloaded to the local folder" -level INFO
  }else{
    Write-Log -Message "Skipping document library : $($library.title) - No files found" -level WARN
  }
}

Write-Log -Message "---------------------------------------------" -level INFO
Write-Log -Message "Download completed" -level INFO
Write-Log -Message "---------------------------------------------" -level INFO
Write-Log -Message "Number of files copied $($Global:filesCopied)" -level INFO
Write-Log -Message "Number of files skipped $($Global:filesSkipped)" -level INFO
Write-Log -Message "---------------------------------------------" -level INFO

Архивировать SharePoint в Azure Blob

Azure Blob storage предлагает различные уровни доступа, каждый из которых имеет свою цену, производительность и доступность. При использовании облачного хранилища вы платите не только за фактическое пространство хранения, которое вы используете, но также должны оплачивать каждую операцию записи и чтения.

При создании новой учетной записи Azure Storage есть четыре уровня на выбор. Премиум-уровень по сути такой же, как SharePoint Online, только стоит на несколько центов меньше ($0,15 за ГБ), чем хранилище SharePoint. Таким образом, для архивирования у нас есть три уровня на выбор:

Горячий уровеньКрутой уровеньАрхивный уровень
Доступность99.9%99%Офлайн
Рекомендуемый срок
сохранения данных
None30 дней180 дней
Задержка доступаМиллисекундыМиллисекундыЧасы
Плата за использованиеБолее высокие затраты на хранение, но более низкие затраты на доступ и транзакцииНизкие затраты на хранение, но более высокие затраты на доступ и транзакцииСамые низкие затраты на хранение, но самые высокие затраты на доступ и транзакции.
Цена за Гб
(первые 50ТБ)
0,018 доллара за ГБ0,01 доллара за ГБ0,00099 доллара за ГБ
Цены указаны за месяц. См. дополнительные детали: Цены на блобы Azure Storage | Microsoft Azure

На мой взгляд, уровень Hot и уровень Cool являются лучшими вариантами для архивирования. Уровень архива, по моему мнению, более подходит для резервного копирования.

Настройка учетной записи Azure Storage

Первый шаг - это настройка учетной записи Azure Storage. Вы можете сначала зарегистрироваться для бесплатной учетной записи, которая предоставляет вам ресурсы Azure на сумму до 200 долларов. После этого вы всегда можете решить, хотите ли вы продолжать или нет.

  1. Откройте портал Azure и нажмите или поищите Учётные записи хранения
  2. Создать новую Учётную запись хранения
  3. Выберите подписку, которую вы хотите использовать
  4. Создайте новую группу ресурсов, назовите её Архив
  5. Введите уникальное имя учетной записи хранилища (должно быть уникальным в Azure!)
  6. Выберите регион, в котором будет храниться данные
  7. Нажмите Далее : Расширенные

На странице расширенных настроек вы можете выбрать уровень доступа, который хотите использовать. Вам потребуется немного прокрутить вниз до хранилища Blob. По умолчанию выбран уровень Hot:

Также неплохо ознакомиться с вкладкой Защита данных. Здесь вы можете настроить, как долго вы хотите хранить файлы и контейнеры в Azure после их удаления.

Когда закончите, нажмите на вкладку Обзор. Если ошибок нет, нажмите Создать.

Создать общий доступ к файлам

Нам потребуется возможность получать доступ к файлам из нашего скрипта PowerShell. Для этого мы собираемся создать новую общую папку. Это позволит нам открыть и смонтировать хранилище Azure blob в нашем проводнике и использовать его в качестве пути загрузки для нашего скрипта.

При создании файлового общего доступа вам нужно будет выбрать уровень. Этот уровень определяет производительность, а также стоимость загрузки и выгрузки файлов из общего доступа. Лучше всего начать с уровня, оптимизированного для транзакций, и сменить его на уровень Cool, как только все файлы будут архивированы.

Подключение общего доступа к файлам в Windows

После того как вы создали общий доступ к файлу, откройте его и нажмите на Подключить. Здесь мы можем выбрать букву диска, которую хотим использовать, и метод аутентификации. По умолчанию используется учетная запись хранения.

После того, как вы выбрали букву диска, нажмите на 'Показать скрипт'. Это даст вам скрипт PowerShell, который вы можете запустить, чтобы смонтировать общий доступ к файлам Azure в вашем проводнике:

Подключение общего доступа к Azure Blob Storage

Архивирование SharePoint в Azure Blob

Создав и смонтировав хранилище Azure Blob, мы можем теперь использовать скрипт PowerShell, представленный в начале этой статьи, чтобы переместить файлы из SharePoint в Azure. Однако имейте в виду, что этот метод загрузит и отправит все файлы через ваше интернет-соединение.

.\Copy-SpSiteToNAS.ps1 -siteUrl https://lazydev.sharepoint.com/sites/lab28 -downloadPath a:\

Скрипту требуется некоторое время, но все файлы в конечном итоге загружаются в хранилище Azure Blob. После того как вы убедитесь, что все файлы скопированы, вы можете удалить данные из SharePoint.

Заметка

Я думаю, что также должно быть возможно запустить скрипт PowerShell внутри Azure Runbook. Но это то, что я разработаю позже.

Решение для резервного копирования от третьих сторон

Использование стороннего решения для резервного копирования также является способом архивирования SharePoint. Многие провайдеры резервного копирования предлагают неограниченное время хранения, а некоторые даже неограниченное пространство для хранения. Поэтому в зависимости от объема данных и количества пользователей, это может иногда быть жизнеспособным решением.

Использование стороннего решения для резервного копирования для архивирования имеет еще одно преимущество: у вас также есть активное решение для резервного копирования ваших данных Microsoft 365. SharePoint сохраняет ваши данные только на 93 дня, после чего вы не сможете их восстановить.

Но есть и обратная сторона этого. Если вы удалили данные из SharePoint, что как раз и является целью архивирования, то смена провайдера резервного копирования станет ужасной задачей. Это означает, что вам придется восстановить все архивированные данные у провайдера резервного копирования, а затем снова архивировать/резервировать их у другого провайдера.

Это то, что вам действительно нужно учитывать. Вы сейчас можете думать, что не переключитесь так скоро, но если провайдер повысит цены, то решение может стать даже дороже, чем покупка дополнительного хранилища SharePoint.

Microsoft Syntex

В ходе мероприятия Microsoft Ignite в октябре 2022 года Microsoft объявила, что собирается ввести архивирование Syntex для SharePoint и Microsoft Teams. Архивирование Syntex добавит многоуровневое хранилище в SharePoint и позволит нам перемещать менее критичный (или старый контент) в более дешевое хранилище.

Заметка

Microsoft выпустила Microsoft 365 Archive, который является частью Syntex. Вы можете узнать больше об этой новой функции в этой статье.

Microsoft Syntex предлагает не только функции архивирования, но и помогает вам улучшить ваш контент, понять и структурировать вашу информацию, а также упростить рабочие процессы. Вы можете узнать больше о Syntex в этой статье от Microsoft.

На данный момент Syntex стоит 5 долларов США с пользователя в месяц. Я не думаю, что хранилище включено в эту цену, поэтому, вероятно, будут дополнительные расходы, аналогично уровням хранения Azure.

Теперь 5 долларов с пользователя могут показаться немного много, но если вы прочитали статью, вы также увидите, что в конце этого года будет доступна функция резервного копирования и восстановления. Это значит, что вам больше не нужно стороннее решение для резервного копирования.

Заключение

Архивирование SharePoint — это процесс, которому рано или поздно нам всем нужно будет уделить внимание. По мере роста наших данных их будет труднее управлять, а затраты на хранение только увеличатся. Я предпочитаю архивировать SharePoint в Azure Blob, так как в этом случае все ваши данные остаются в облаке, и вам не нужно беспокоиться о защите локально хранящихся данных.

Microsoft Syntex может стать действительно интересным вариантом для архивирования и резервного копирования. Убедитесь, что вы подписались на рассылку ниже, чтобы быть в курсе событий.

Я надеюсь, что эта статья помогла вам с архивированием SharePoint. Если у вас есть вопросы, просто оставьте комментарий ниже.