SharePoint Online: Copy Attachments from List to Document Library using PowerShell
Requirement: Copy all attachments from a SharePoint Online List to Document Library.
How to Copy Attachments from SharePoint Online List?
Would you like to copy attachments from a list to a document library in SharePoint Online? If so, this handy guide will show you how! With just a few simple steps, you can easily move files between lists and libraries. You can use this method to copy multiple attachments, either from one list item or from all items of a list at once.
Here is the trick to copy all attachments from the 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 Online: Copy Attachments to Document Library using PowerShell
Let’s copy all attachments from a list item 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"
#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 the 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 from a list to a document library:
#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 in the document library for each list item (based on the 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,[string]::Empty)
$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 another post to copy attachments to another list: SharePoint Online: Copy Attachment from One List to Another
In conclusion, By using the methods outlined in this tutorial, you can easily and efficiently transfer attachments from a List to a Document Library to take advantage of the capabilities offered by SharePoint Online, such as version control, search and retrieval, and collaboration. By automating the process, you can save time and resources, and ensure that the attachments are properly stored and maintained.
Hello, this is a big help, thank you for putting it together.
In the PnP script, is there an option to check if the document already exists in the Document Library I am copying it into, and only overwrite it if it’s changed?