msgraph-sdk-powershell icon indicating copy to clipboard operation
msgraph-sdk-powershell copied to clipboard

Add -AsByteStream option to Get-MgUserPhotoContent

Open stuartluscombe opened this issue 3 years ago • 3 comments

When I used to retrieve user photo data via a REST API call I would be given the photo data as a byte stream which I could get convert to a base64 string for comparison with another system we have that present the user photo as a base64 string.

Here is a snippet of my code that uses the direct REST call:

$body = @{grant_type = "client_credentials"; resource = $resource; client_id = $AzureClientID; client_secret = $AzureClientSecret}
$oauth = Invoke-RestMethod -Method Post -Uri $loginURL/$AzureTenantDomain/oauth2/token?api-version=1.0 -Body $body

$headerParams = @{'Authorization' = "$($oauth.token_type) $($oauth.access_token)"}
[uri]$uriGraphEndpoint = "https://graph.microsoft.com/v1.0/users/$($User.mail)/photo/" + '$value'

try {
    $response = Invoke-WebRequest -Method Get $uriGraphEndpoint.AbsoluteUri -Headers $headerParams -ErrorAction SilentlyContinue

    try {
        $Worker = Get-WDWorker -Credential $WDCredentials -RequestType Photo,Contact -WorkerID $User.EmployeeNumber -Environment $WDEnvironment

        if([Convert]::ToBase64String($response.Content) -ne $Worker.ImageData) {
            Write-Verbose "Photo for $($User.Name) is different"
            $WDResponse = Set-WDWorkerPhoto -Credential $WDCredentials -WorkerID $User.EmployeeNumber -PhotoData ([Convert]::ToBase64String($response.Content)) -Environment $WDEnvironment

            if($WDResponse -match '^\S{32}$') {
                Write-Verbose "Workday photo for $($User.Name) updated successfully."
            } else {
                Write-Verbose "Workday photo update for $($User.Name) failed."
            }
        } else {
            Write-Verbose "Photo for $($User.Name) is the same"
        }
    }

With Get-MgUserPhotoContent as it works today I have to first save the photo as a file before then converting it for comparison and then delete the file, which seems unnecessary.

Is there any possibility of getting this cmdlet updated so that it has something like a -AsByteStream option?

stuartluscombe avatar Aug 19 '22 12:08 stuartluscombe

Thanks for opening the feature request.

The ability to change the output type of the command by specifying a -AsByteStream is currently not supported by the code generator. I've opened a feature request at https://github.com/Azure/autorest.powershell/issues/996 for this to be added to the code generator.

As a workaround, you can use Invoke-MgGraphRequest to get photo as bytes as shown below:

$Response = Invoke-MgGraphRequest -Uri $uriGraphEndpoint -OutputType HttpResponseMessage
$ContentInBytes = $Response.Content.ReadAsByteArrayAsync().GetAwaiter().GetResult()

peombwa avatar Sep 01 '22 20:09 peombwa

$Response = Invoke-MgGraphRequest -Uri $uriGraphEndpoint -OutputType HttpResponseMessage
$ContentInBytes = $Response.Content.ReadAsByteArrayAsync().GetAwaiter().GetResult()

This is not working:

$Response = Invoke-MgGraphRequest -Uri 'https://graph.microsoft.com/beta/users/[email protected]/photo/$value' -OutputType HttpResponseMessage
Invoke-MgGraphRequest : Request returned Non-Json response of Image, Please specify '-OutputFilePath'

Is there a way to get the photo content as stream/byte in a variable instead to save the picture on local disk?

Thanks!

julmsy avatar Sep 02 '22 12:09 julmsy

Thanks for opening the feature request.

The ability to change the output type of the command by specifying a -AsByteStream is currently not supported by the code generator. I've opened a feature request at Azure/autorest.powershell#996 for this to be added to the code generator.

As a workaround, you can use Invoke-MgGraphRequest to get photo as bytes as shown below:

$Response = Invoke-MgGraphRequest -Uri $uriGraphEndpoint -OutputType HttpResponseMessage
$ContentInBytes = $Response.Content.ReadAsByteArrayAsync().GetAwaiter().GetResult()

Thanks for opening the feature request.

I am however getting the same error result from that command as mentioned by @julmsy

stuartluscombe avatar Sep 05 '22 09:09 stuartluscombe

Sorry for the late response.

The provided snippet works on my end. $ContentInBytes is a byte array, you'll just need to pass it to [Convert]::ToBase64String($ContentInBytes) to converting to base64 string. Which version of the SDK are you using?

image

peombwa avatar Aug 31 '23 17:08 peombwa

Sorry for the late response.

The provided snippet works on my end. $ContentInBytes is a byte array, you'll just need to pass it to [Convert]::ToBase64String($ContentInBytes) to converting to base64 string. Which version of the SDK are you using?

image

@peombwa, using the method you have shown with v2.4.0 of the module does give me the data I need. It would still be good though if the -AsByteStream option were added to Get-MgUserPhotoContent so as to avoid making the API call directly.

stuartluscombe avatar Sep 04 '23 12:09 stuartluscombe

Sorry for the late response. The provided snippet works on my end. $ContentInBytes is a byte array, you'll just need to pass it to [Convert]::ToBase64String($ContentInBytes) to converting to base64 string. Which version of the SDK are you using? image

using the method you have shown with v2.4.0 of the module does give me the data I need. It would still be good though if the -AsByteStream option were added to Get-MgUserPhotoContent so as to avoid making the API call directly.

That's right. However, the feature request depends on an upstream dependency supporting -AsBytes - https://github.com/Azure/autorest.powershell/issues/996.

peombwa avatar Oct 20 '23 15:10 peombwa