Oh, Grafikon. Obećana zemlja i pouka da nikada ne vjerujemo praznim obećanjima. Čak i 2025., još uvijek mučen nedostatkom jedinstvenog standarda, pri čemu svaki PG unutar Microsofta radi svoje stvari, a neki potpuno ignoriraju Graph. Dodajte ovom bezveznom automatski generiranom kodu, bol koju dodatno pogoršava još lošija (ili nepostojeća) dokumentacija, i sve će biti jednostavno savršeno.
Dakle, evo me, pišem još jedan naklapan članak nakon što sam proveo zadnjih nekoliko sati čitajući, pretražujući, kopirajući, petljajući, psujući i dekompilirajući u potrazi za jednostavnim odgovorom na još jednostavnije pitanje: Kako postaviti korisnikovu fotografiju sa slike pohranjene na webu? Odgovor možete pronaći na kraju članka, ostalo je gomila nepotrebnih detalja pomiješanih s nekim naklapanjima. Upozorio sam te! 🙂
Evo opet problema. Želimo postaviti sliku profila Entra/Microsoft 365 korisnika. Do sada biste trebali znati da stare metode za to, kao što je korištenje Set-UserPhoto cmdlet, nedavno su zastarjeli u korist Graph metode. Konkretno, možemo koristiti Ažurirajte metodu profilePhotoi podudaranje Set-MgUserPhotoContent cmdlet. Na primjer:
Set-MgUserPhotoContent -UserId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -InFile "C:\Pictures\12345.png"
Sve je u redu, ali što ako ne možemo ili ne možemo pohraniti slike na lokalni disk i umjesto toga ih želimo dohvatiti s URL-a? Pa, očito -U datoteci parametar je implementacija “na strani klijenta”, jer ne možemo očekivati da će se temeljna Graph API metoda oslanjati na pristup lokalnim datotekama. Dakle, umjesto toga samo trebamo proslijediti neobrađene slikovne podatke, zar ne? I sigurno Graph SDK pruža parametar za to?
Brzi pregled dokumentacije govori nam da je to doista tako, putem -Podaci parametar. Ono što nam dokumentacija ne govori je kako koristiti navedeni parametar i kakvu vrstu unosa očekuje. Proći a System.IO.FileStream objekt? Bez kockica. Proći a System.IO.MemoryStream objekt? Pokušajte ponovno. Ili će pogriješiti ili će inzistirati da navedete vrijednost za -U datoteci također, što na neki način poražava cijelu svrhu.
Kako do sada znam da od Graph SDK-a za PowerShell ne očekujem ništa osim loše implementacije cmdleta, umjesto toga sam se okrenuo “neobrađenom” Graph API zahtjevu. Eto i gle, evo što dokumentacija kaže: U tijelu zahtjeva uključite binarne podatke fotografije. A u slučaju da vam je gore navedeno malo nejasno i pokušate pogledati primjere, evo čime ćete uživati u očima:
Sada imate sve potrebne informacije, zar ne? Oh, i ako pogledate navodni uzorak PowerShell koda, moći ćete uživati ne samo u još jednom spominjanju Binarni podaci za slikuali i nepostojeći parametar. Nemoj samo da voliš svo ovo autogenerirano sranje!
Budući da s dokumentacijom nisam uspio ništa, okrenuo sam se pretraživanju i nakon što nisam pronašao nijedan relevantan rezultat na internetu, u svom sam očaju čak zamolio neke od naših voljenih AI suradnika za pomoć. Nepotrebno je reći da je to bio još jedan gubitak vremena, pa sam se na kraju okrenuo dobrim starim praksama obrnutog inženjeringa. Započinjanje s Fiddlerovim praćenjem kako bi se ispitao točan format korisnih podataka koje koristi cmdlet/Graph API metoda:
Gornji snimak zaslona bilježi zahtjev koji odgovara uspješnom izvršenju Set-MgUserPhotoContent cmdlet. Ako pogledate dio nosivosti, zatvoren u zelenom okviru, možete vidjeti gore spomenuto Binarni podaci za slikukoji užasno izgleda kao objekt generiran putem Get-Content cmdlet. Ipak, prosljeđivanje neobrađenog Graph API zahtjeva s takvim sadržajem rezultiralo je pogreškama, kao što je prikazano u nastavku:
Iako usporedba binarnih podataka nije tako jednostavna, sličnosti postoje. Jedna stvar koja se ističe je razlika u vrijednosti duljine sadržaja, što daje koristan savjet. Nažalost, pokušavajući iskoristiti znanje dobiveno iz gore navedenih tragova s Set-MgUserPhotoContent cmdlet rezultirao nultim uspjehom. Tako da sam u tom trenutku jednostavno odustao od toga i okrenuo se dobrom starom Invoke-MgGraphRequest umjesto toga.
Bez daljnjeg odlaganja, evo nekoliko primjera kako možete postaviti korisnikovu fotografiju putem Set-MgUserPhotoContent:
$bytes = [System.IO.File]::ReadAllBytes("D:\Downloads\1.jpg")
$stream = [System.IO.MemoryStream]::new($bytes)
Invoke-MgGraphRequest -Method PUT -Uri "https://graph.microsoft.com/v1.0/users/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/photo/`$value" -Body $stream -ContentType 'image/jpeg'
Alternativni pristup putem StreamReader-a:
$image3 = [System.IO.StreamReader]::new("D:\Downloads\1.jpg").BaseStream
Invoke-MgGraphRequest -Method PUT -Uri "https://graph.microsoft.com/v1.0/users/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/photo/`$value" -Body $image3 -ContentType 'image/jpeg'
I, konačno, kako postaviti korisnikovu fotografiju izravno s URL-a slike, koristeći svojstvo streama sirovog sadržaja:
#Fetch the image $image4 = Invoke-WebRequest -Uri "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8d/Tabby_Kitten_on_Blue_Throw.jpg/1024px-Tabby_Kitten_on_Blue_Throw.jpg" #Set it as user's profile photo Invoke-MgGraphRequest -Method PUT -Uri "https://graph.microsoft.com/v1.0/users/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/photo/`$value" -Body $image4.RawContentStream -ContentType 'image/jpeg'
Na kraju dana, čak ni nakon što sam proveo neko vrijeme dekompilirajući, nisam mogao shvatiti kako točno -Podaci parametar od Set-MgUserPhotoContent cmdlet bi trebao raditi i što prihvaća kao unos. Pa sam zaključio da je tu brbljanje najmudrija odluka, pogotovo sada kada je zadatak koji smo si postavili konačno izvršen.
Posljednja stvar koju treba napomenuti je da ćete možda morati iskoristiti -Vi ste u BasicParsingu parametar od Invoke-WebRequest cmdlet, ovisno o verziji PowerShell-a koju koristite. I time možemo zatvoriti ovaj članak. Nadamo se da će informacije u njemu pomoći još nekom jadniku i naučiti te umjetne inteligencije “doktorske razine” ponešto.
///AŽURIRATI. Kao dodatni savjet, evo kako postaviti fotografiju sa slike pohranjene u SPO/ODFB. Zapravo postoji mnogo načina za dobivanje neobrađenih slikovnih podataka, ali zadržimo se na onom koji ima najviše smisla za prosječnog Joea. To jest, umjesto da morate pružiti a siteId, listId/driveId i itemIdmožemo koristiti API za pretraživanjeili odgovarajući Invoke-MgQuerySearch cmdlet, za dohvaćanje pojedinosti o stavci prema URL-u (putem upita “staza”). Jednostavno zatražite pogonska stavka vrsta entiteta.
Nakon što imamo skup ID-ova koji identificiraju sliku, možemo koristiti Get-MgDriveItem ili Get-MgSiteListItemDriveItem cmdlet za dohvaćanje ‘@microsoft.graph.downloadUrl’ aspekt. To nam daje unaprijed provjereni URL za preuzimanje koji zatim možemo koristiti s Invoke-WebRequest cmdlet za dohvaćanje slike, bez brige o autentifikaciji.

