cli-microsoft365
cli-microsoft365 copied to clipboard
New sample script: Download attachments from a SharePoint Online list
Docs | |
---|---|
Author | Ruud |
Original Post | https://www.sharepointdiary.com/2017/01/sharepoint-online-download-attachments-from-list-using-powershell.html |
Description | Download attachments from a SharePoint Online list. |
Keywords | Migration |
Hi @plamber / @waldekmastykarz, Could you please assign this to me?
Thank you. All yours
@plamber / @waldekmastykarz, As discussed in #2661, we don't have AttachmentFiles property currently so I created with M365 CLI and classic API to complete this script as shown below:
Are you okay with this plan or I have to wait until AttachmentFiles property is avilable?
Function Get-ListAttachments() {
param
(
[Parameter(Mandatory = $true)] [string] $AccessToken,
[Parameter(Mandatory = $true)] [string] $SiteURL,
[Parameter(Mandatory = $true)] [string] $ListTitle,
[Parameter(Mandatory = $true)] [int] $ItemId
)
Try {
$ListItemAttachmentsEndPoint = "$($SiteURL)/_api/web/lists/getbytitle('$($ListTitle)')/items($($ItemId))/AttachmentFiles"
$Header = @{
"Authorization" = "Bearer $($AccessToken)"
"Accept" = "application/json; odata=verbose"
"Content-Type" = "application/json "
}
$ListItemAttachments = Invoke-RestMethod -Uri $ListItemAttachmentsEndPoint -Headers $Header -Method Get
return $ListItemAttachments.d.results
}
Catch {
write-host -f Red "Error Getting List Item Attachments!" $_.Exception.Message
}
}
Function Download-ListAttachments() {
param
(
[Parameter(Mandatory = $true)] [string] $TenantName,
[Parameter(Mandatory = $true)] [string] $SiteURL,
[Parameter(Mandatory = $true)] [string] $ListTitle,
[Parameter(Mandatory = $true)] [string] $DownloadDirectory
)
Try {
#Get All Items from the List
$ListItems = m365 spo listitem list --webUrl $SiteURL --title $ListTitle -o json | ConvertFrom-Json -AsHashtable
#Create download directory if it doesn't exist
If (!(Test-Path -path $DownloadDirectory)) {
New-Item $DownloadDirectory -type directory
}
#Iterate through each list item
Foreach ($Item in $ListItems) {
$AccessToken = m365 util accesstoken get --resource "https://$($TenantName).sharepoint.com" --new
#Get All attachments from the List Item
$Attachments = Get-ListAttachments -AccessToken $AccessToken -SiteURL $SiteURL -ListTitle $ListTitle -ItemId $Item.Id
foreach ($Attachment in $Attachments) {
$TargetFilePath = "$($DownloadDirectory)/$($Item.Id)_$($Attachment.FileName)"
#Download attachment
m365 spo file get --webUrl $SiteURL --url $Attachment.ServerRelativeUrl --asFile --path $TargetFilePath
}
}
write-host -f Green "List Attachments Downloaded Successfully!"
}
Catch {
write-host -f Red "Error Downloading List Attachments!" $_.Exception.Message
}
}
#Set Parameters
$TenantName = "spridermvp"
$SiteRelativePath = "sites/dev"
$ListTitle = "SPOL Download"
$DownloadDirectory = $PSScriptRoot
$SiteURL = "https://$($TenantName).sharepoint.com/$($SiteRelativePath)"
#Call the function to copy list items
Download-ListAttachments -TenantName $TenantName -SiteURL $SiteURL -ListTitle $ListTitle -DownloadDirectory $DownloadDirectory
We should check #2661. I will create some issues for it and come back to you
Hi @sprider, First of all. Thank you for your efforts. These are highly appreciated.
I created an issue for the m365 spo listitem attachment list
command (#2730). We should use that one for the example we are referencing here.
On the other hand, I like your approach of solving the issue by calling directly the REST API of SharePoint and using the CLI to retrieve the required tokens. I think this should become a sample by its own. @waldekmastykarz: what do you think about this? I would reuse the sample of @sprider and give it a different title: "How to call the SharePoint REST API using the CLI". What do you think?
Cheers
Hi @sprider,
First of all. Thank you for your efforts. These are highly appreciated.
I created an issue for the
m365 spo listitem attachment list
command (#2730). We should use that one for the example we are referencing here.On the other hand, I like your approach of solving the issue by calling directly the REST API of SharePoint and using the CLI to retrieve the required tokens. I think this should become a sample by its own. @waldekmastykarz: what do you think about this? I would reuse the sample of @sprider and give it a different title: "How to call the SharePoint REST API using the CLI". What do you think?
Cheers
Perfect, Thank you @plamber
Hi @sprider, First of all. Thank you for your efforts. These are highly appreciated.
I created an issue for the
m365 spo listitem attachment list
command (#2730). We should use that one for the example we are referencing here.On the other hand, I like your approach of solving the issue by calling directly the REST API of SharePoint and using the CLI to retrieve the required tokens. I think this should become a sample by its own. @waldekmastykarz: what do you think about this? I would reuse the sample of @sprider and give it a different title: "How to call the SharePoint REST API using the CLI". What do you think?
Cheers
I think there is a room for both: from the functional point of view, we'd preferably want to have a dedicated command. That said, there might always be the case when you want to do something that's not covered by the CLI, so showing how to get an access token is also valuable.
Hi, just created the issue #2731 and assigned @sprider to it. We should take your example and explain that you can still use the CLI to simplify the creation of scripts that are not yet covered by the CLI. This might be a good sample.
Thank you, Patrick
As #2730 has been implemented it looks like we can now progress this sample script.
@sprider are you happy to continue working on this?
@garrytrinder Thank you for checking with me. Unfortunately, I am currently a bit busy and may be unable to take this issue. Could you please keep this open so that someone can pick up this?
No problem, thank you for the reply 👍🏻
Opening up
I can attempt to work on the sample.
Great to hear @reshmee011!
@milanholemans : where do I add the sample script? I have amended the sample code provided by @sprider to use the m365 cli to get the attachments
param ( [Parameter(Mandatory = $true)] [string] $SiteURL, [Parameter(Mandatory = $true)] [string] $ListTitle, [Parameter(Mandatory = $true)] [string] $DownloadDirectory )
$m365Status = m365 status if ($m365Status -match "Logged Out") { Write-Host "Logging in the User!" m365 login --authType browser }
Try {
#Get All Items from the List
$ListItems = m365 spo listitem list --webUrl $SiteURL --listTitle $ListTitle | ConvertFrom-Json
#Create download directory if it doesn't exist
If (!(Test-Path -path $DownloadDirectory)) {
New-Item $DownloadDirectory -type directory
}
#Iterate through each list item
Foreach ($Item in $ListItems) {
#Get All attachments from the List Item
$Attachments = m365 spo listitem attachment list --webUrl $SiteURL --listTitle $ListTitle --itemId $Item.Id | ConvertFrom-Json
foreach ($Attachment in $Attachments) {
$TargetFilePath = "$($DownloadDirectory)/$($Item.Id)_$($Attachment.FileName)"
#Download attachment
m365 spo file get --webUrl $SiteURL --url $Attachment.ServerRelativeUrl --asFile --path $TargetFilePath
}
}
write-host -f Green "List Attachments Downloaded Successfully!"
}
Catch {
write-host -f Red "Error Downloading List Attachments!" $_.Exception.Message
}
Hi @reshmee011, great to hear! You can add the script under ./docs/sample-scripts/spo
. Make sure that you don't forget to add the assets/sample.json
file.