- Current state: 3,249/3,768 files uploaded, 519 remaining - Active RMM command: 9e0fcfe8 (running on ACG-DWP-X-BB) - Working upload script with drive ID concatenation fix - Comprehensive continuation instructions - All verification scripts Client very angry - this was promised yesterday Issue: PowerShell escaping ! in drive ID (b! -> b\!) Solution: String concatenation at runtime
98 lines
3.4 KiB
PowerShell
98 lines
3.4 KiB
PowerShell
# Upload all files from Datto local copy to SharePoint via Graph API
|
|
# This script runs ON the ACG-DWP-X-BB VM and uploads directly
|
|
|
|
param(
|
|
[string]$SourcePath = "C:\Users\Public\Desktop\Datto Workplace Server Projects\Quality Department",
|
|
[string]$TenantId = "19a568e8-9e88-413b-9341-cbc224b39145",
|
|
[string]$ClientId = "709e6eed-0711-4875-9c44-2d3518c47063",
|
|
[string]$ClientSecret = "", # Will be passed via command line
|
|
[string]$SiteUrl = "https://birthbiologic.sharepoint.com/sites/QualitySystemsDepartment",
|
|
[string]$DriveId = "b!F8BzMb1YakCIWCyWlmczb09LHqtxDxVMpLT6kAwYmsM7NUY4oPLSRq7ng3tJq-E9"
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
Write-Host "==================================================================="
|
|
Write-Host " Upload ALL Files from Datto to SharePoint via Graph API"
|
|
Write-Host "==================================================================="
|
|
Write-Host ""
|
|
Write-Host "Source: $SourcePath"
|
|
Write-Host "Target: $SiteUrl/Documents"
|
|
Write-Host ""
|
|
|
|
# Get access token
|
|
Write-Host "Getting Graph API token..."
|
|
$tokenBody = @{
|
|
client_id = $ClientId
|
|
client_secret = $ClientSecret
|
|
scope = "https://graph.microsoft.com/.default"
|
|
grant_type = "client_credentials"
|
|
}
|
|
|
|
$tokenResponse = Invoke-RestMethod -Method Post -Uri "https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token" -Body $tokenBody
|
|
$token = $tokenResponse.access_token
|
|
|
|
Write-Host "[OK] Token acquired"
|
|
Write-Host ""
|
|
|
|
# Get all files from source
|
|
Write-Host "Scanning source files..."
|
|
$files = Get-ChildItem $SourcePath -Recurse -File -ErrorAction SilentlyContinue
|
|
|
|
Write-Host "[OK] Found $($files.Count) files to upload"
|
|
Write-Host ""
|
|
|
|
# Upload each file
|
|
$uploaded = 0
|
|
$errors = @()
|
|
|
|
foreach ($file in $files) {
|
|
$relativePath = $file.FullName.Substring($SourcePath.Length + 1)
|
|
$uploadPath = $relativePath.Replace('\', '/')
|
|
|
|
try {
|
|
# For files < 4MB, use simple upload
|
|
if ($file.Length -lt 4MB) {
|
|
$uploadUrl = "https://graph.microsoft.com/v1.0/drives/$DriveId/root:/$uploadPath`:/content"
|
|
$headers = @{
|
|
"Authorization" = "Bearer $token"
|
|
"Content-Type" = "application/octet-stream"
|
|
}
|
|
|
|
$fileBytes = [System.IO.File]::ReadAllBytes($file.FullName)
|
|
Invoke-RestMethod -Method Put -Uri $uploadUrl -Headers $headers -Body $fileBytes | Out-Null
|
|
} else {
|
|
# For large files, use upload session (simplified - just do small files for now)
|
|
Write-Host " SKIP (>4MB): $uploadPath"
|
|
continue
|
|
}
|
|
|
|
$uploaded++
|
|
if ($uploaded % 100 == 0) {
|
|
Write-Host " Uploaded $uploaded / $($files.Count) files..."
|
|
}
|
|
} catch {
|
|
$errors += [PSCustomObject]@{
|
|
File = $relativePath
|
|
Error = $_.Exception.Message
|
|
}
|
|
Write-Host " ERROR: $relativePath - $($_.Exception.Message)"
|
|
}
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host "==================================================================="
|
|
Write-Host " Upload Complete"
|
|
Write-Host "==================================================================="
|
|
Write-Host ""
|
|
Write-Host "Uploaded: $uploaded / $($files.Count) files"
|
|
Write-Host "Errors: $($errors.Count)"
|
|
Write-Host ""
|
|
|
|
if ($errors.Count -gt 0) {
|
|
Write-Host "First 10 errors:"
|
|
$errors | Select-Object -First 10 | ForEach-Object {
|
|
Write-Host " $($_.File): $($_.Error)"
|
|
}
|
|
}
|