1
votes

my goal is: Get the items within the folders in a SharePoint 2010 library. I'm struggling trying to get some Items from a SharePoint 2010 Library using CSOM with PowerShell. I tried three different methods that i found in the internet but still without success. Also the Microsoft's Documentation is really sh*t in this aspect, hope somebody can help me. So here we go:

1.Method A

            [Microsoft.SharePoint.Client.FileInformation]$fileInfo = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($ctx, $file.ServerRelativeUrl);
            [System.IO.FileStream]$writeStream = [System.IO.File]::Open("$($libraryTargetPath)\$($file.Name)", [System.IO.FileMode]::Create);
            $fileInfo.Stream.CopyTo($writeStream);
            $writeStream.Close();

With the A method I get this error:

Method invocation failed because [System.Net.ConnectStream] doesn't contain a method named 'CopyTo'.
+ $fileInfo.Stream.CopyTo <<<< ($writeStream);
+ CategoryInfo : InvalidOperation: (CopyTo:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound

The [System.Net.ConnectStream] can't find the method CopyTo
I was lookign information about this, in the System.Net namespace and in the "Microsoft.SharePoint.Client.FileInformation" class but without success :(

2.Method B

            $binary = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($ctx, $file.ServerRelativeUrl)
            $Action = [System.IO.FileMode]::Create
            $new = "$($libraryTargetPath)\$($file.Name)"
            $stream = New-Object System.IO.FileStream $new, $Action
            $writer = New-Object System.IO.BinaryWriter($stream)
            $writer.write($binary)
            $writer.Close()

Method B don't give me a error, but in stead of downloading the Items, it makes empty files in the destination folder. So this method isn't downloading the items, just making new files.

3.Method C

            $binary = $file.OpenBinary()
            $stream = New-Object System.IO.FileStream("$($libraryTargetPath)\$($file.Name)"), Create
            $writer = New-Object System.IO.BinaryWriter($stream)
            $writer.write($binary)
            $writer.Close()

I'm not sure if method C belongs to CSOM or to the SharPoint built-in Server side client, if it's so please let me know. This is the error i'm getting:

Method invocation failed because [Microsoft.SharePoint.Client.File] doesn't contain a method named 'OpenBinary'. At C:\Users\Administrator\Desktop\SharePointOnPremisesBackUp\SharePointOnPremisesBackUp.ps1:77 char:31
+ $binary = $file.OpenBinary <<<< ()
+ CategoryInfo : InvalidOperation: (OpenBinary:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound

And here PowerShell can't find the OpenBinary() method in Microsoft.SharePoint.Client.File and there is nearly not information about this method.

Here is the complete function I'm trying to use:

function GetDocumentLibs ($ctx, $web)
{
    Function  IterateFoldersRecursively([Microsoft.SharePoint.Client.Folder]$folder, [Microsoft.SharePoint.Client.ClientContext]$ctx)
    {
      # make sure that the "Web.Context.Url" is the current web url
      if ($web.Context.Url.StartsWith($SiteCollectionUrl) -eq $true)
      {
        $files = $folder.Files
        $ctx.Load($folder.Files)
        $ctx.Load($folder.Folders)
        $ctx.ExecuteQuery()

        foreach ($subFolder in $folder.Folders)
        {
            IterateFoldersRecursively $subFolder $ctx
        }

        # Check if folder Exist and Skip

        $libraryTargetPath = "$($TargetPath)\$($folder.ServerRelativeUrl.Replace('/', '\'))"
        New-Item -Path $libraryTargetPath -ItemType Directory -Force

            foreach ($file in $files)
            {
            # Method 1
            [Microsoft.SharePoint.Client.FileInformation]$fileInfo = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($ctx, $file.ServerRelativeUrl);
            [System.IO.FileStream]$writeStream = [System.IO.File]::Open("$($libraryTargetPath)\$($file.Name)", [System.IO.FileMode]::Create);
            $fileInfo.Stream.CopyTo($writeStream)
            $writeStream.Close()

            # Method 2
            $binary = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($ctx, $file.ServerRelativeUrl)
            $Action = [System.IO.FileMode]::Create
            $new = "$($libraryTargetPath)\$($file.Name)"
            $stream = New-Object System.IO.FileStream $new, $Action
            $writer = New-Object System.IO.BinaryWriter($stream)
            $writer.write($binary)
            $writer.Close()

            # Method 3
            $binary = $file.OpenBinary()
            $stream = New-Object System.IO.FileStream("$($libraryTargetPath)\$($file.Name)"), Create
            $writer = New-Object System.IO.BinaryWriter($stream)
            $writer.write($binary)
            $writer.Close()

            # delete folder
            }
       }
    }
    $folder = $web.GetFolderByServerRelativeUrl($web.ServerRelativeUrl)
    $ctx.Load($folder)
    $ctx.ExecuteQuery()

    IterateFoldersRecursively $folder $ctx
}                                               

the tools I'm using:

  1. Sapien's PowerShell Studio
  2. PowerShell V2 with CSOM
  3. SharePoint 2010 OnPremises

Please if you have any Solution, Reference, Documentation or tutorial that can be useful tell me. Thanks in advance.

1

1 Answers

1
votes

After a lot of research i found a solution and decide to use this method:

function GetDocumentLibs ($ctx, $web)
{
    $site = $ctx.Site
    $ctx.Load($site)
    $ctx.ExecuteQuery()
    $siteUrl = $site.Url

    Function IterateFoldersRecursively([Microsoft.SharePoint.Client.Folder]$folder, [Microsoft.SharePoint.Client.ClientContext]$ctx)
    {
        if ($web.Context.Url.StartsWith($SiteCollectionUrl) -eq $true)
        {
            $files = $folder.Files
            $ctx.Load($folder.Files)
            $ctx.Load($folder.Folders)
            $ctx.ExecuteQuery()

            foreach ($subFolder in $folder.Folders)
            {
                IterateFoldersRecursively $subFolder $ctx
            }

            $targetPath = "$($TargetPath)\$($folder.ServerRelativeUrl.Replace('/', '\'))"
            New-Item -Path $targetPath -ItemType Directory -Force

            foreach ($file in $files)
            {
                $client = new-object System.Net.WebClient
                $client.UseDefaultCredentials = $true
                $client.DownloadFile("$($siteUrl)$($file.ServerRelativeUrl)", "$($targetPath)\$($file.Name)")
            }
        }
    }
    $folder = $web.GetFolderByServerRelativeUrl($web.ServerRelativeUrl)
    $ctx.Load($folder)
    $ctx.ExecuteQuery()

    IterateFoldersRecursively $folder $ctx
}

Remember to implement some exception handling. I hope this is helpful for somebody with the same problem.