0
votes

I am trying to fetch Recent file from sharepoint which is updated every month. Instead of manually downloading the file in local, I want to directly fetch from sharepoint and do analysis.

My sharepoint url looks likes this:

https://abc.sharepoint.com/_layouts/15/sharepoint.aspx

Where abc is my organisation name like apple, wipro so on.

I tried following this link:

Python - Download files from SharePoint site

## Sharepoint access
## pip install Office365-REST-Python-Client
from office365.runtime.auth.authentication_context import AuthenticationContext
from office365.sharepoint.client_context import ClientContext

ctx_auth = AuthenticationContext("https://abc.sharepoint.com/_layouts/15/sharepoint.aspx")
ctx_auth.acquire_token_for_user('**@abc.com', '***')

 I get the error as:

  An error occurred while retrieving auth cookies from 
  https://abc.sharepoint.com/_layouts/15/sharepoint.aspx/_vti_bin/idcrl.svc
  False

Secondly, someone has shared me the link to sharepoint and I have access to download it. It looks like:

https://abc-my.sharepoint.com/personal/persons_name_abc_com/_layouts/15/onedrive.aspx?view=4

Inside this there is folder named Analysis Files. In Analysis Files folder there is excel file which I have to download. How can I do it using python 3?

2

2 Answers

0
votes

SharePoint App-Only is the older, but still very relevant, model of setting up app-principals. This model works for both SharePoint Online and SharePoint 2013/2016 on-premises and is ideal to prepare your applications for migration from SharePoint on-premises to SharePoint Online.

I am not familiar with Python3 but you can use the below code sample in your code as it uses REST API.

Please refer the following articles and let me know if you have any questions

SharePoint App-Only - https://sprider.blog/spol-download-file-from-library-using-sharepoint-app-only-access-and-powershell

Graph API - https://sprider.blog/download-sharepoint-file-using-microsoft-graph-api

How to get Tenant ID - https://sprider.blog/get-office-365-tenant-id-from-domain-name

Tenant Name - abc as per your code example.

Client Id and Secret can be retrived from SharePoint or Azure AD App Registration


###### Global Static Variables - Start ######
$grantType = "client_credentials"
$principal = "00000003-0000-0ff1-ce00-000000000000"
###### Global Static Variables - End ######

###### Global Tenant Specific Variables - Start ######
$m365TenantId = "yourtenantguid" 
$targetHost = "yourtenantname.sharepoint.com"
$appClientId = "clientid-from-previous-section"
$appClientSecret = "clientsecret-from-previous-section"
###### Global Tenant Specific Variables - End ######

###### Site/File Path Variables - Start ######
$targetFolder = $PSScriptRoot
$siteRelativeUrl = "sites/yoursite"
$folderRelativeUrl = "your-document-library-name"
$fileName = "your-file-name.png"
###### Site/File Path Variables - Start ######

###### Helper Functions - Start ######
function Add-Working-Directory([string]$workingDir, [string]$logDir) {
    if (!(Test-Path -Path $workingDir)) {
        try {
            $suppressOutput = New-Item -ItemType Directory -Path $workingDir -Force -ErrorAction Stop
            $msg = "SUCCESS: Folder '$($workingDir)' for CSV files has been created."
            Write-Host -ForegroundColor Green $msg
        }
        catch {
            $msg = "ERROR: Failed to create '$($workingDir)'. Script will abort."
            Write-Host -ForegroundColor Red $msg
            Exit
        }
    }
    if (!(Test-Path -Path $logDir)) {
        try {
            $suppressOutput = New-Item -ItemType Directory -Path $logDir -Force -ErrorAction Stop
            $msg = "SUCCESS: Folder '$($logDir)' for log files has been created."
            Write-Host -ForegroundColor Green $msg
        }
        catch {
            $msg = "ERROR: Failed to create log directory '$($logDir)'. Script will abort."
            Write-Host -ForegroundColor Red $msg
            Exit
        }
    }
}
function Add-Log([string]$message, [string]$logFile) {
    $lineItem = "[$(Get-Date -Format "dd-MMM-yyyy HH:mm:ss") | PID:$($pid) | $($env:username) ] " + $message
    Add-Content -Path $logFile $lineItem
}
function Get-AccessToken {
    try { 
        $message = "Getting Accesstoken..."
        Add-Log $message $Global:logFile

        $tokenEndPoint = "https://accounts.accesscontrol.windows.net/$m365TenantId/tokens/oauth/2"
        $client_Id = "$appClientId@$m365TenantId"
        $resource = "$principal/$targetHost@$m365TenantId"

        $requestHeaders = @{
            "Content-Type" = "application/x-www-form-urlencoded"
        }

        $requestBody = @{
            client_id     = $client_Id
            client_secret = $appClientSecret
            grant_type    = $grantType
            resource      = $resource
        }

        $response = Invoke-RestMethod -Method 'Post' -Uri $tokenEndPoint -Headers $requestHeaders -Body $requestBody 
        $accesstoken = $response.access_token

        $message = "Accesstoken received."
        Add-Log $message $Global:logFile

        return $accesstoken
    } 
    catch {  
        $statusCode = $_.Exception.Response.StatusCode.value__ 
        $statusDescription = $_.Exception.Response.StatusDescription

        $message = "StatusCode: $statusCode"
        Add-Log $message $Global:logFile

        $message = "StatusDescription : $statusDescription"
        Add-Log $message $Global:logFile

        return $null
    }
}
function Download-File([string]$fileUrl, [string]$targetFilePath) {

    $accessToken = Get-AccessToken

    if (![string]::IsNullOrEmpty($accessToken)) {

        try {
            $fileUri = New-Object System.Uri($fileUrl)

            $wc = New-Object System.Net.WebClient
            $wc.Headers.Add("Authorization", "Bearer $accessToken")
            $job = $wc.DownloadFileTaskAsync($fileUri, $targetFilePath)

            $message = "Downloading file $fileUrl at $targetFilePath."
            Add-Log $message $Global:logFile

            while (!$job.IsCompleted) {
                sleep 1
            }

            if ($job.Status -ne "RanToCompletion") {
                $message = "Failed to download file."
                Add-Log $message $Global:logFile
            }
            else {
                $message = "File downloaded."
                Add-Log $message $Global:logFile
            }
        }
        catch {
            $statusCode = $_.Exception.Response.StatusCode.value__ 
            $statusDescription = $_.Exception.Response.StatusDescription

            $message = "StatusCode: $statusCode"
            Add-Log $message $Global:logFile

            $message = "StatusDescription : $statusDescription"
            Add-Log $message $Global:logFile

            $message = "Failed to download file."
            Add-Log $message $Global:logFile
        }
    }
    else {
        $message = "Unable to get Accesstoken."
        Add-Log $message $Global:logFile
    }
}
###### Helper Functions - End ######

###### Main Program - Start ######

###### Log Setup - Start ######
$currentDirectoryPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
$workingDirectory = $currentDirectoryPath

$logDirectoryName = "Logs"
$logDirectory = "$workingDirectory/$logDirectoryName"

$logFileName = "$(Get-Date -Format "yyyyMMddTHHmmss")_downloadjobexecution.log"
$Global:logFile = "$logDirectory/$logFileName"

Add-Working-Directory $workingDirectory $logDirectory
###### Log Setup - Start ######

Write-Host -ForegroundColor Yellow "WARNING: Minimal output will appear on the screen."
Write-Host -ForegroundColor Yellow "         Please look at the log file '$($logFile)'"

$message = "**************************************** SCRIPT STARTED ****************************************"
Add-Log $message $Global:logFile

###### Download File - Start ######

$targetFilePath = Join-Path $targetFolder $fileName
$fileUrl = "https://$targetHost/$siteRelativeUrl/_api/Web/GetFolderByServerRelativeUrl('$folderRelativeUrl')/Files('$fileName')/`$value"
Download-File $fileUrl $targetFilePath
###### Download File - End ######

$message = "**************************************** SCRIPT COMPLETED ****************************************"
Add-Log $message $Global:logFile

###### Main Program - End ######
-1
votes

The error shows that there is something wrong when you get authorization. You could connect to SharePoint site like below:

tenant_url= "https://{tenant}.sharepoint.com"
ctx_auth = AuthenticationContext(tenant_url)

site_url="https://{tenant}.sharepoint.com/sites/{yoursite}"

ctx_auth.acquire_token_for_user("username","password"):