SharePoint Online: Copy Attachments from List to Document Library using PowerShell

Requirement: Copy all attachments from a SharePoint Online List to Document Library
sharepoint copy attachment from list to document library

How to Copy Attachments from SharePoint Online List?
Here is the trick to copy all attachments from SharePoint Online list: SharePoint stores list item attachments by creating sub-folders for each list item based on the item id under a folder called "Attachments". 
  • Append "Attachments" to your list URL. E.g. If your list URL is: https://tenant.sharepoint.com/lists/project, then the URL is: https://tenant.sharepoint.com/lists/project/attachments
  • Map the URL you framed in the above step as a network drive. Go to Windows explorer >> Right-click on "This PC" (or "My Computer") >> Choose "Map Network Drive" >> Enter the URL and finish that wizard. 
  • This opens the list attachments in the File Explorer view, where you can see and copy attachments from the list.
    sharepoint copy list attachment to document library
You can also use SharePoint Designer to navigate to the "Attachments" folder and copy attachments for any list.

SharePoint Online: Copy Attachments to Document Library using PowerShell
Let's copy all attachments from a list item to 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"

#Set Parameters
$SiteURL= "https://crescent.sharepoint.com/sites/marketing"
$ListName= "Projects"
$ListItemID = 1
$DocumentLibraryURL = "/Sites/Marketing/Project Documents/" #Relative URL - Must end with /

#Setup Credentials to connect
$Cred = Get-Credential

#Setup the context
$Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
$Ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.UserName,$Cred.Password)

#Get the List Item
$List = $Ctx.Web.Lists.GetByTitle($ListName)
$ListItem = $List.GetItemByID($ListItemID)
$Attachments = $ListItem.AttachmentFiles
$Ctx.Load($Attachments)
$Ctx.ExecuteQuery()
    
#Get All attachments from the List Item
Write-host "Total Attachments Found:"$Attachments.count
ForEach($Attachment in $Attachments)
{
    #Get attachment from List Item
    $File = $Ctx.Web.GetFileByServerRelativeUrl($Attachment.ServerRelativeUrl)
    $Ctx.Load($file)
    $Ctx.ExecuteQuery()

    #Copy attachment to Document Library
    $File.CopyTo($DocumentLibraryURL+$File.Name, $True)
    $Ctx.ExecuteQuery()
    Write-host "Attachment Copied:"$File.name
}
This PowerShell script copies all attachments from the list item with item id "1" to an existing document library "Project Documents" on the same site.

PowerShell to Copy Attachments from All List Items in SharePoint Online
Let's copy all attachments of given list items to a 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"

Function Copy-ListAttachments()
{
    Param
    (
        [Parameter(Mandatory=$true)] [string] $SiteURL,
        [Parameter(Mandatory=$true)] [string] $ListName,
        [Parameter(Mandatory=$true)] [string] $DocumentLibraryName
    )
    
    Try {
        #Setup Credentials to connect
        $Cred = Get-Credential

        #Setup the context
        $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
        $Ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.UserName,$Cred.Password)

        #Get the Document Library 
        $DocumentLibrary = $Ctx.Web.Lists.GetByTitle($DocumentLibraryName)
        $Ctx.Load($DocumentLibrary.RootFolder)
        $Ctx.Load($DocumentLibrary.RootFolder.Folders)
        $Ctx.ExecuteQuery()

        #Get all List Items with attachments
        $Query = New-Object Microsoft.SharePoint.Client.CamlQuery
        $Query.ViewXml = "<View Scope='RecursiveAll'><Query><Where><Eq><FieldRef Name='Attachments' /><Value Type='Boolean'>1</Value></Eq></Where></Query></View>"
        $List = $Ctx.Web.Lists.GetByTitle($ListName)
        $ListItems = $List.GetItems($Query)
        $Ctx.Load($ListItems)
        $Ctx.ExecuteQuery()
        
        #Iterate through each list item
        ForEach($ListItem in $ListItems)
        {
            #Get All attachments from the List Item
            $Attachments = $ListItem.AttachmentFiles
            $Ctx.Load($Attachments)
            $Ctx.ExecuteQuery()

            #Create New Folder for each List Item
            $Folders = $DocumentLibrary.RootFolder.Folders | Select -ExpandProperty Name
            If($Folder -notcontains $ListItem.Id)
            {
                $Folder = $DocumentLibrary.RootFolder.Folders.Add($ListItem.Id)
                $Ctx.ExecuteQuery()
            }

            ForEach($Attachment in $Attachments)
            {
                #Get attachment from List Item
                $File = $Ctx.Web.GetFileByServerRelativeUrl($Attachment.ServerRelativeUrl)
                $Ctx.Load($file)
                $Ctx.ExecuteQuery()

                #Copy attachment to Document Library
                $TargetFileURL = $DocumentLibrary.RootFolder.ServerRelativeUrl+"/"+$ListItem.Id+"/"+$File.Name
                $File.CopyTo($TargetFileURL, $True)
                $Ctx.ExecuteQuery()
                Write-host "Attachment Copied:"$TargetFileURL
            }
        }
    }
    Catch {
        write-host -f Red "Error Copying List Attachments!" $_.Exception.Message
    } 
}

#Call the function to copy attachments
Copy-ListAttachments -SiteURL "https://crescent.sharepoint.com/sites/marketing" -ListName "Projects" -DocumentLibraryName "Project Documents"

PnP PowerShell to Copy List Item Attachments to Document Library
Here is the PnP PowerShell way to copy attachments.
#Parameters
$SiteURL = "https://crescent.sharepoint.com/sites/marketing"
$ListName = "Projects"
$ListItemID = "1"
$DocumentLibraryURL = "/Sites/Marketing/ProjectDocuments"

#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -Credentials (Get-Credential)

#Get the List Item
$ListItem = Get-PnPListItem -List $ListName -Id $ListItemID

#Get All Attachments of the List Item
$Attachments = Get-PnPProperty -ClientObject $ListItem -Property "AttachmentFiles"

#Copy Attachment File to Document Library 
$Attachments | ForEach-Object { Copy-PnPFile -SourceUrl $_.ServerRelativeUrl –TargetUrl "$DocumentLibraryURL/$($_.FileName)" -OverwriteIfAlreadyExists:$True -Force}

Copy List Attachments to Document library using PnP PowerShell
How about copying all attachments to a documents library, folder wise? Let's create folders the document library for each list item (based on list item id) and attachments.
#Parameters
$SiteURL = "https://crescent.sharepoint.com/sites/marketing"
$ListName = "Projects"
$DocumentLibraryName = "Project Documents"

#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -Credentials (Get-Credential)

#Get All List Items with Attachments
$SPQuery = "<View Scope='RecursiveAll'><Query><Where><Eq><FieldRef Name='Attachments' /><Value Type='Boolean'>1</Value></Eq></Where></Query></View>"
$ListItems = Get-PnPListItem -List $ListName -Query $SPQuery

#Get the Web and Document Library
$Web = Get-PnPWeb
$DocumentLibrary = Get-PnPList $DocumentLibraryName -Includes RootFolder

ForEach($ListItem in $ListItems)
{
    #Get All Attachments of the List Item
    $Attachments = Get-PnPProperty -ClientObject $ListItem -Property "AttachmentFiles"

    #Create Folder for List Item Attachments in the document library
    $FolderURL = "$($DocumentLibrary.RootFolder.ServerRelativeUrl)/$($ListItem.ID)"
    $FolderSiteRelativeURL = $FolderURL.Replace($Web.ServerRelativeUrl,"")
    $Folder = Resolve-PnPFolder -SiteRelativePath $FolderSiteRelativeURL

    #Copy Attachment File to Document Library 
    $Attachments | ForEach-Object { Copy-PnPFile -SourceUrl $_.ServerRelativeUrl –TargetUrl "$FolderURL/$($_.FileName)" -OverwriteIfAlreadyExists:$True -Force}
}
Here is my another post to copy attachment to another list: SharePoint Online: Copy Attachment from One List to Another
SharePoint Online: Copy Attachments from List to Document Library using PowerShell SharePoint Online: Copy Attachments from List to Document Library using PowerShell Reviewed by Salaudeen Rajack on March 16, 2019 Rating: 5

No comments:

Please Login and comment to get your questions answered!

Powered by Blogger.