version 1.0
This commit is contained in:
@@ -0,0 +1,464 @@
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$WebUrl,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$OutputPath,
|
||||
|
||||
[switch]$IncludeHiddenLibraries
|
||||
)
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
function Initialize-SharePointPowerShell {
|
||||
if (-not (Get-PSSnapin -Name Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue)) {
|
||||
Add-PSSnapin Microsoft.SharePoint.PowerShell
|
||||
}
|
||||
}
|
||||
|
||||
function Ensure-Directory {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Path
|
||||
)
|
||||
|
||||
if (-not [System.IO.Directory]::Exists($Path)) {
|
||||
[System.IO.Directory]::CreateDirectory($Path) | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
function Get-SafePathSegment {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Name
|
||||
)
|
||||
|
||||
$invalidChars = [System.IO.Path]::GetInvalidFileNameChars()
|
||||
$safeName = $Name
|
||||
|
||||
foreach ($char in $invalidChars) {
|
||||
$safeName = $safeName.Replace($char, "_")
|
||||
}
|
||||
|
||||
$safeName = $safeName.Trim()
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($safeName)) {
|
||||
return "_"
|
||||
}
|
||||
|
||||
return $safeName
|
||||
}
|
||||
|
||||
function Combine-PathSegments {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$BasePath,
|
||||
|
||||
[string[]]$Segments = @()
|
||||
)
|
||||
|
||||
$combinedPath = $BasePath
|
||||
|
||||
foreach ($segment in $Segments) {
|
||||
if (-not [string]::IsNullOrWhiteSpace($segment)) {
|
||||
$combinedPath = [System.IO.Path]::Combine($combinedPath, $segment)
|
||||
}
|
||||
}
|
||||
|
||||
return $combinedPath
|
||||
}
|
||||
|
||||
function Convert-SPFieldValue {
|
||||
param(
|
||||
[Parameter(ValueFromPipeline = $true)]
|
||||
$Value
|
||||
)
|
||||
|
||||
if ($null -eq $Value) {
|
||||
return $null
|
||||
}
|
||||
|
||||
if ($Value -is [System.DateTime]) {
|
||||
return $Value.ToString("o")
|
||||
}
|
||||
|
||||
if ($Value -is [Microsoft.SharePoint.SPFieldUserValue]) {
|
||||
return @{
|
||||
LookupId = $Value.LookupId
|
||||
LookupValue = $Value.LookupValue
|
||||
Email = $Value.User.Email
|
||||
LoginName = $Value.User.LoginName
|
||||
}
|
||||
}
|
||||
|
||||
if ($Value -is [Microsoft.SharePoint.SPFieldUserValueCollection]) {
|
||||
return @($Value | ForEach-Object { Convert-SPFieldValue $_ })
|
||||
}
|
||||
|
||||
if ($Value -is [Microsoft.SharePoint.SPFieldLookupValue]) {
|
||||
return @{
|
||||
LookupId = $Value.LookupId
|
||||
LookupValue = $Value.LookupValue
|
||||
}
|
||||
}
|
||||
|
||||
if ($Value -is [Microsoft.SharePoint.SPFieldLookupValueCollection]) {
|
||||
return @($Value | ForEach-Object { Convert-SPFieldValue $_ })
|
||||
}
|
||||
|
||||
if ($Value -is [Microsoft.SharePoint.SPFieldUrlValue]) {
|
||||
return @{
|
||||
Url = $Value.Url
|
||||
Description = $Value.Description
|
||||
}
|
||||
}
|
||||
|
||||
if ($Value -is [System.Guid]) {
|
||||
return $Value.ToString()
|
||||
}
|
||||
|
||||
if ($Value -is [System.Collections.IEnumerable] -and -not ($Value -is [string])) {
|
||||
return @($Value | ForEach-Object { Convert-SPFieldValue $_ })
|
||||
}
|
||||
|
||||
$typeName = $Value.GetType().FullName
|
||||
if ($typeName -like "*TaxonomyFieldValue") {
|
||||
return @{
|
||||
Label = $Value.Label
|
||||
TermGuid = $Value.TermGuid
|
||||
WssId = $Value.WssId
|
||||
}
|
||||
}
|
||||
|
||||
if ($typeName -like "*TaxonomyFieldValueCollection") {
|
||||
return @($Value | ForEach-Object {
|
||||
@{
|
||||
Label = $_.Label
|
||||
TermGuid = $_.TermGuid
|
||||
WssId = $_.WssId
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return $Value
|
||||
}
|
||||
|
||||
function Get-FieldTextValue {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Microsoft.SharePoint.SPField]$Field,
|
||||
|
||||
$RawValue
|
||||
)
|
||||
|
||||
try {
|
||||
return $Field.GetFieldValueAsText($RawValue)
|
||||
}
|
||||
catch {
|
||||
return $null
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ItemFieldTextValue {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Microsoft.SharePoint.SPListItem]$Item,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$InternalName
|
||||
)
|
||||
|
||||
if (-not $Item.Fields.ContainsField($InternalName)) {
|
||||
return $null
|
||||
}
|
||||
|
||||
return Get-FieldTextValue -Field $Item.Fields[$InternalName] -RawValue $Item[$InternalName]
|
||||
}
|
||||
|
||||
function Get-FileMetadataObject {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Microsoft.SharePoint.SPWeb]$Web,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Microsoft.SharePoint.SPList]$List,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Microsoft.SharePoint.SPFile]$File
|
||||
)
|
||||
|
||||
$item = $File.Item
|
||||
$fieldMetadata = @()
|
||||
|
||||
if ($null -ne $item) {
|
||||
foreach ($field in $item.Fields) {
|
||||
$rawValue = $item[$field.InternalName]
|
||||
|
||||
$fieldMetadata += [PSCustomObject]@{
|
||||
InternalName = $field.InternalName
|
||||
Title = $field.Title
|
||||
TypeAsString = $field.TypeAsString
|
||||
TextValue = Get-FieldTextValue -Field $field -RawValue $rawValue
|
||||
Value = Convert-SPFieldValue $rawValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [PSCustomObject]@{
|
||||
ExportedAtUtc = [System.DateTime]::UtcNow.ToString("o")
|
||||
Web = [PSCustomObject]@{
|
||||
Title = $Web.Title
|
||||
Url = $Web.Url
|
||||
ServerRelativeUrl = $Web.ServerRelativeUrl
|
||||
Id = $Web.ID.ToString()
|
||||
}
|
||||
Library = [PSCustomObject]@{
|
||||
Title = $List.Title
|
||||
Id = $List.ID.ToString()
|
||||
RootFolderUrl = $List.RootFolder.ServerRelativeUrl
|
||||
BaseTemplate = [int]$List.BaseTemplate
|
||||
}
|
||||
File = [PSCustomObject]@{
|
||||
Name = $File.Name
|
||||
Url = $File.Url
|
||||
ServerRelativeUrl = $File.ServerRelativeUrl
|
||||
UniqueId = $File.UniqueId.ToString()
|
||||
Length = $File.Length
|
||||
TimeCreated = $File.TimeCreated.ToString("o")
|
||||
TimeLastModified = $File.TimeLastModified.ToString("o")
|
||||
CheckOutType = $File.CheckOutType.ToString()
|
||||
Level = $File.Level.ToString()
|
||||
MajorVersion = $File.MajorVersion
|
||||
MinorVersion = $File.MinorVersion
|
||||
}
|
||||
Item = if ($null -ne $item) {
|
||||
[PSCustomObject]@{
|
||||
Id = $item.ID
|
||||
UniqueId = $item.UniqueId.ToString()
|
||||
ContentTypeId = $item.ContentTypeId.ToString()
|
||||
ContentTypeName = $item.ContentType.Name
|
||||
Created = if ($null -ne $item["Created"]) { ([datetime]$item["Created"]).ToString("o") } else { $null }
|
||||
Modified = if ($null -ne $item["Modified"]) { ([datetime]$item["Modified"]).ToString("o") } else { $null }
|
||||
CreatedBy = Get-ItemFieldTextValue -Item $item -InternalName "Author"
|
||||
ModifiedBy = Get-ItemFieldTextValue -Item $item -InternalName "Editor"
|
||||
Fields = $fieldMetadata
|
||||
}
|
||||
}
|
||||
else {
|
||||
$null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Write-MetadataJson {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
$MetadataObject,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Path
|
||||
)
|
||||
|
||||
$json = $MetadataObject | ConvertTo-Json -Depth 10
|
||||
[System.IO.File]::WriteAllText($Path, $json, [System.Text.Encoding]::UTF8)
|
||||
}
|
||||
|
||||
function Write-ManifestRow {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[pscustomobject]$Row,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$ManifestPath
|
||||
)
|
||||
|
||||
$append = [System.IO.File]::Exists($ManifestPath)
|
||||
$Row | Export-Csv -Path $ManifestPath -NoTypeInformation -Delimiter ";" -Encoding UTF8 -Append:$append
|
||||
}
|
||||
|
||||
function Get-RelativeFilePathSegments {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Microsoft.SharePoint.SPList]$List,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Microsoft.SharePoint.SPFile]$File
|
||||
)
|
||||
|
||||
$rootUrl = $List.RootFolder.ServerRelativeUrl.TrimEnd("/")
|
||||
$fileUrl = $File.ServerRelativeUrl
|
||||
$relativeUrl = $fileUrl.Substring($rootUrl.Length).TrimStart("/")
|
||||
|
||||
return @($relativeUrl.Split("/") | ForEach-Object { Get-SafePathSegment $_ })
|
||||
}
|
||||
|
||||
function Export-SPFile {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Microsoft.SharePoint.SPWeb]$Web,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Microsoft.SharePoint.SPList]$List,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Microsoft.SharePoint.SPFile]$File,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$FilesRootPath,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$MetadataRootPath,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$ManifestPath
|
||||
)
|
||||
|
||||
$relativeSegments = Get-RelativeFilePathSegments -List $List -File $File
|
||||
$relativeDirectorySegments = @()
|
||||
|
||||
if ($relativeSegments.Count -gt 1) {
|
||||
$relativeDirectorySegments = $relativeSegments[0..($relativeSegments.Count - 2)]
|
||||
}
|
||||
|
||||
$safeLibraryName = Get-SafePathSegment $List.Title
|
||||
$fileDirectory = Combine-PathSegments -BasePath ([System.IO.Path]::Combine($FilesRootPath, $safeLibraryName)) -Segments $relativeDirectorySegments
|
||||
$metadataDirectory = Combine-PathSegments -BasePath ([System.IO.Path]::Combine($MetadataRootPath, $safeLibraryName)) -Segments $relativeDirectorySegments
|
||||
|
||||
Ensure-Directory -Path $fileDirectory
|
||||
Ensure-Directory -Path $metadataDirectory
|
||||
|
||||
$fileName = $relativeSegments[-1]
|
||||
$localFilePath = [System.IO.Path]::Combine($fileDirectory, $fileName)
|
||||
$metadataPath = [System.IO.Path]::Combine($metadataDirectory, "$fileName.metadata.json")
|
||||
|
||||
[System.IO.File]::WriteAllBytes($localFilePath, $File.OpenBinary())
|
||||
|
||||
$metadata = Get-FileMetadataObject -Web $Web -List $List -File $File
|
||||
Write-MetadataJson -MetadataObject $metadata -Path $metadataPath
|
||||
|
||||
$manifestRow = [PSCustomObject]@{
|
||||
WebUrl = $Web.Url
|
||||
LibraryTitle = $List.Title
|
||||
FileName = $File.Name
|
||||
FileServerRelativeUrl = $File.ServerRelativeUrl
|
||||
FileUniqueId = $File.UniqueId.ToString()
|
||||
FileLength = $File.Length
|
||||
LocalFilePath = $localFilePath
|
||||
LocalMetadataPath = $metadataPath
|
||||
ExportedAtUtc = [System.DateTime]::UtcNow.ToString("o")
|
||||
}
|
||||
|
||||
Write-ManifestRow -Row $manifestRow -ManifestPath $ManifestPath
|
||||
}
|
||||
|
||||
function Export-SPFolder {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Microsoft.SharePoint.SPWeb]$Web,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Microsoft.SharePoint.SPList]$List,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Microsoft.SharePoint.SPFolder]$Folder,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$FilesRootPath,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$MetadataRootPath,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$ManifestPath,
|
||||
|
||||
[ref]$FileCount
|
||||
)
|
||||
|
||||
foreach ($file in $Folder.Files) {
|
||||
Export-SPFile -Web $Web -List $List -File $file -FilesRootPath $FilesRootPath -MetadataRootPath $MetadataRootPath -ManifestPath $ManifestPath
|
||||
$FileCount.Value++
|
||||
}
|
||||
|
||||
foreach ($subFolder in $Folder.SubFolders) {
|
||||
if ($subFolder.Name -eq "Forms") {
|
||||
continue
|
||||
}
|
||||
|
||||
Export-SPFolder -Web $Web -List $List -Folder $subFolder -FilesRootPath $FilesRootPath -MetadataRootPath $MetadataRootPath -ManifestPath $ManifestPath -FileCount $FileCount
|
||||
}
|
||||
}
|
||||
|
||||
function Export-SPDocumentLibrary {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Microsoft.SharePoint.SPWeb]$Web,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[Microsoft.SharePoint.SPList]$List,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$FilesRootPath,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$MetadataRootPath,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$ManifestPath
|
||||
)
|
||||
|
||||
Write-Host ("Exportiere Bibliothek: {0}" -f $List.Title)
|
||||
$fileCount = 0
|
||||
|
||||
Export-SPFolder -Web $Web -List $List -Folder $List.RootFolder -FilesRootPath $FilesRootPath -MetadataRootPath $MetadataRootPath -ManifestPath $ManifestPath -FileCount ([ref]$fileCount)
|
||||
|
||||
Write-Host (" Dateien exportiert: {0}" -f $fileCount)
|
||||
}
|
||||
|
||||
Initialize-SharePointPowerShell
|
||||
|
||||
$resolvedOutputPath = [System.IO.Path]::GetFullPath($OutputPath)
|
||||
$filesRootPath = [System.IO.Path]::Combine($resolvedOutputPath, "Files")
|
||||
$metadataRootPath = [System.IO.Path]::Combine($resolvedOutputPath, "Metadata")
|
||||
$manifestPath = [System.IO.Path]::Combine($resolvedOutputPath, "manifest.csv")
|
||||
|
||||
Ensure-Directory -Path $resolvedOutputPath
|
||||
Ensure-Directory -Path $filesRootPath
|
||||
Ensure-Directory -Path $metadataRootPath
|
||||
|
||||
if ([System.IO.File]::Exists($manifestPath)) {
|
||||
[System.IO.File]::Delete($manifestPath)
|
||||
}
|
||||
|
||||
$web = $null
|
||||
|
||||
try {
|
||||
$web = Get-SPWeb -Identity $WebUrl -ErrorAction Stop
|
||||
|
||||
$documentLibraries = @(
|
||||
$web.Lists | Where-Object {
|
||||
$_.BaseType -eq [Microsoft.SharePoint.SPBaseType]::DocumentLibrary -and
|
||||
($IncludeHiddenLibraries -or -not $_.Hidden) -and
|
||||
-not $_.IsCatalog
|
||||
}
|
||||
)
|
||||
|
||||
if ($documentLibraries.Count -eq 0) {
|
||||
Write-Warning ("Keine Dokumentbibliotheken im Web gefunden: {0}" -f $WebUrl)
|
||||
return
|
||||
}
|
||||
|
||||
Write-Host ("Gefundene Bibliotheken: {0}" -f $documentLibraries.Count)
|
||||
|
||||
foreach ($library in $documentLibraries) {
|
||||
Export-SPDocumentLibrary -Web $web -List $library -FilesRootPath $filesRootPath -MetadataRootPath $metadataRootPath -ManifestPath $manifestPath
|
||||
}
|
||||
|
||||
Write-Host ("Export abgeschlossen. Ausgabe: {0}" -f $resolvedOutputPath)
|
||||
}
|
||||
finally {
|
||||
if ($null -ne $web) {
|
||||
$web.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user