Uploading folders in sharepoint from powershell

Copper Contributor

My below code successfully read a folder and uploades the subfolder one by one as a zip file in SharePoint. But if any of my file is of Zip extension, it gives me an error. I would like to know how can I fix my existing code below to handle the zip files as well so that it loads both the zip folder and non-zip files and folders in the SharePoint. I tried multiple tings like removing .zip extension in the Create-Archive and file but it does not work. error received:

2020-12-09T15:49:05.7979920Z Invoke-RestMethod : The remote server returned an error: (400) Bad Request. 2020-12-09T15:49:05.7981233Z At D:\a\r1\a_DevOpsScripts\ReleaseNoteScripts\UploadInSharePoint.ps1:55 char:17 2020-12-09T15:49:05.7982104Z + ... $response = Invoke-RestMethod $uploadURLObject.uploadUrl -Method 'PUT ... 2020-12-09T15:49:05.7982819Z + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2020-12-09T15:49:05.7983312Z + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc 2020-12-09T15:49:05.7983979Z eption 2020-12-09T15:49:05.7984369Z + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

 

 

param($ClientID,$ClientSecret,$WId,$RName,$RReqFor,$SPid,$LibId)
$tempDirectory = "temp"
# arguments defined from predefined variables in argument section of powershell stage of pipeline
$workingDirectory = "$WId"
$CLIENT_ID = "$ClientID"
$CLIENT_SECRET = "$ClientSecret"
$SharePointSiteId = "$SPid"
$LibraryId = "$LibId"
$azx = "$RName" +"_"+"$RReqFor"
$adx = ($azx.Split("[")[0])
$artifactname = $adx.Substring(0,$adx.Length-1)


# Get access token
Function GET-TOKEN 
{
    param($clientId, $clientSecret)
    $tokenHeaders = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
    $tokenHeaders.Add("Content-Type", "application/x-www-form-urlencoded")
    $tokenBody = "client_id="+ $clientId + "&scope=https%3A//graph.microsoft.com/.default&client_secret=" + $clientSecret + "&grant_type=client_credentials"
    $tokenBody
    $tokenResponse = Invoke-RestMethod 'https://login.microsoftonline.com/test.onmicrosoft.com/oauth2/v2.0/token' -Method 'POST' -Headers $tokenHeaders -Body $tokenBody
    return $tokenResponse    
}


# upload the file
Function UPLOAD-FILE
{
    param($workingDir, $tempDir, $clientId, $clientSecret, $artifactname)
  
    
    Get-ChildItem $workingDir | ForEach-Object {
    
    $name = $_.FullName.Split("\")[-1]
    CREATE-ARCHIVE -workingDir $_.FullName -tempDir $tempDir -name $name
    $file = $_.FullName + "\" +$tempDir + "\" + "$($name).zip"         
    
    $fileSize = (Get-Item $file).length       
    $uploadURLObject = GET-UPLOADLINK -clientId $clientId -clientSecret $clientSecret -artifactname $name
    $tokenObject = GET-TOKEN -clientId $clientId -clientSecret $clientSecret
    $uploadHeaders = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
    $uploadHeaders.Add("Content-Type", "application/json")
    $uploadHeaders.Add("Content-Range", "bytes " + 0 +"-" + ($fileSize-1) + "/" + $fileSize)
    $uploadHeaders.Add("Content-Length", $fileSize)
    $uploadHeaders.Add("Authorization", "Bearer "+ $tokenObject.access_token)    
    $uploadBody = [System.IO.File]::ReadAllBytes($file)
    $response = Invoke-RestMethod $uploadURLObject.uploadUrl -Method 'PUT' -Headers $uploadHeaders -Body $uploadBody
    $response | ConvertTo-Json  
    REMOVE-TEMPDIR -workingDir $_.FullName -tempDir $tempDirectory
    }
    
    
}
Function GET-UPLOADLINK
{
    param($clientId, $clientSecret, $artifactname)
    $tokenObject = GET-TOKEN -clientId $clientId -clientSecret $clientSecret
    $uploadLinkRequestHeaders = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
    $uploadLinkRequestHeaders.Add("Content-Type", "application/json")
    $uploadLinkRequestHeaders.Add("Authorization", "Bearer "+ $tokenObject.access_token)
    $uploadLinkRequestBody = ""     
    #update the actual link  
    $fullname = "https://graph.microsoft.com/v1.0/sites/$($SPid)/drives/$($LibId)/root/children/"    
    $comname = $fullname + $artifactname    
    $uploadLinkResponse = Invoke-RestMethod "$($comname).zip/createUploadSession" -Method 'POST' -Headers $uploadLinkRequestHeaders -Body $uploadLinkRequestBody
    $uploadLinkResponse | ConvertTo-Json
    return $uploadLinkResponse    
}

Function CREATE-ARCHIVE
{
    param($workingDir, $tempDir, $name )
    write-host $workingDir
    cd $workingDir
    md $tempDir
    #Compress-Archive -Path $workingDir -DestinationPath $workingDir\$tempDir\$artifactname
    Compress-Archive -Path $workingDir -DestinationPath $workingDir\$tempDir\$name
}

Function REMOVE-TEMPDIR
{
    param($workingDir, $tempDir)
    #This will be the last step
    rm $workingDir\$tempDir -Recurse   
}



UPLOAD-FILE -workingDir $workingDirectory -tempDir $tempDirectory -clientId $CLIENT_ID -clientSecret $CLIENT_SECRET -artifactname $artifactname
powershell

 

2 Replies

@Ankit007 

 

You could modify the UPLOAD-FILE function so that it identifies files with a .zip extension and skips running the CREATE-ARCHIVE function, just assigns them to the $file variable.  

 

 

Function UPLOAD-FILE
{
    param($workingDir, $tempDir, $clientId, $clientSecret, $artifactname)
  
    Get-ChildItem $workingDir | ForEach-Object {
    $name = $_.FullName.Split("\")[-1]
    if ($name -contains ".zip") {
        #skip running CREATE-ARCHIVE
        $file = $_.FullName + "\" +$tempDir + "\" + "$($name)"         
    }
    else {
         CREATE-ARCHIVE -workingDir $_.FullName -tempDir $tempDir -name $name
         $file = $_.FullName + "\" +$tempDir + "\" + "$($name).zip"         
    }
    $fileSize = (Get-Item $file).length       
    $uploadURLObject = GET-UPLOADLINK -clientId $clientId -clientSecret $clientSecret -artifactname $name
    $tokenObject = GET-TOKEN -clientId $clientId -clientSecret $clientSecret
    $uploadHeaders = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
    $uploadHeaders.Add("Content-Type", "application/json")
    $uploadHeaders.Add("Content-Range", "bytes " + 0 +"-" + ($fileSize-1) + "/" + $fileSize)
    $uploadHeaders.Add("Content-Length", $fileSize)
    $uploadHeaders.Add("Authorization", "Bearer "+ $tokenObject.access_token)    
    $uploadBody = [System.IO.File]::ReadAllBytes($file)
    $response = Invoke-RestMethod $uploadURLObject.uploadUrl -Method 'PUT' -Headers $uploadHeaders -Body $uploadBody
    $response | ConvertTo-Json  
    REMOVE-TEMPDIR -workingDir $_.FullName -tempDir $tempDirectory
    }
    
    
}

 

 

Thanks,

Steve Correia

tumtum1973

@Ankit007 

 

You could modify the UPLOAD-FILE function to skip files with a .zip extension and assign them to the $file value for upload.

 

# upload the file
Function UPLOAD-FILE
{
    param($workingDir, $tempDir, $clientId, $clientSecret, $artifactname)
  
    
    Get-ChildItem $workingDir | ForEach-Object {
    
    $name = $_.FullName.Split("\")[-1]
    if ($name -contains ".zip") {
          #skip file
          $file = $_.FullName + "\" +$tempDir + "\" + "$($name)"
    }
    else {
         CREATE-ARCHIVE -workingDir $_.FullName -tempDir $tempDir -name $name
         $file = $_.FullName + "\" +$tempDir + "\" + "$($name).zip"
    }
    
    $fileSize = (Get-Item $file).length       
    $uploadURLObject = GET-UPLOADLINK -clientId $clientId -clientSecret $clientSecret -artifactname $name
    $tokenObject = GET-TOKEN -clientId $clientId -clientSecret $clientSecret
    $uploadHeaders = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
    $uploadHeaders.Add("Content-Type", "application/json")
    $uploadHeaders.Add("Content-Range", "bytes " + 0 +"-" + ($fileSize-1) + "/" + $fileSize)
    $uploadHeaders.Add("Content-Length", $fileSize)
    $uploadHeaders.Add("Authorization", "Bearer "+ $tokenObject.access_token)    
    $uploadBody = [System.IO.File]::ReadAllBytes($file)
    $response = Invoke-RestMethod $uploadURLObject.uploadUrl -Method 'PUT' -Headers $uploadHeaders -Body $uploadBody
    $response | ConvertTo-Json  
    REMOVE-TEMPDIR -workingDir $_.FullName -tempDir $tempDirectory
    }
    
    
}