Want to save yourself some coding? See the preview release of GooglePhotosCli using this library...
This is an unofficial Google Photos REST API library targeting .NET 8.0.
Note: Older projects that require .NET Standard 2.0 please use version 1.x of this library.
If you find this library of use then please give it a thumbs-up by giving this repository a :star: ... :wink:
If you wish to interact with your Google Photos media items/albums then there are official PHP and Java Client Libraries. However if you're looking for a comprehensive .NET library then you were out of luck... until now :)
The CasCap.Apis.GooglePhotos library wraps up all the available functionality of the Google Photos REST API in easy to use methods.
Note: Before you jump in and use this library you should be aware that the Google Photos Library API has some key limitations. The biggest of these is that the API only allows the upload/addition of images/videos to the library, no edits or deletion are possible and have to be done manually via https://photos.google.com.
When you create your photos application, you must first create an OAuth login details using the Google API Console and retrieve a Client ID and a Client Secret.
Using your Google Account the steps are*;
*Note: the above instructions are correct as of 2022-04-06.
Install the package into your project using NuGet (see details here).
For .NET Core applications using dependency injection the primary API usage is to call IServiceCollection.AddGooglePhotos in the Startup.cs ConfigureServices method.
//Startup.cs
using Microsoft.Extensions.DependencyInjection;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddGooglePhotos();
}
}
There are 4 mandatory configuration options that must be passed;
There are 5 possible authorisation scopes which designate the level of access you wish to give, these scopes can be combined if required;
Best practise is to assign the lowest access level possible to meet your requirements. If you wish to go against best practise and give your application unfettered access to your media collection then use Access and Sharing scopes combined.
The recommended method of setting these mandatory options is via the appsettings.json file;
// appsettings.json
{
...
"CasCap": {
"GooglePhotosOptions": {
// This is the email address of the Google Account.
"User": "your.email@mydomain.com",
// There are 5 security scopes, which can be combined.
"Scopes": [
"ReadOnly"
//"AppendOnly",
//"AppCreatedData",
//"Access",
//"Sharing"
],
// The ClientId and ClientSecret are provided by the Google Console after you register your own application.
"ClientId": "012345678901-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.apps.googleusercontent.com",
"ClientSecret": "abcabcabcabcabcabcabcabc",
}
}
...
}
Alternatively you can pass the options into the AddGooglePhotos method;
//Startup.cs
using Microsoft.Extensions.DependencyInjection;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddGooglePhotos(options =>
{
options.User = "your.email@mydomain.com";//replace with **your** info
options.ClientId = "012345678901-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.apps.googleusercontent.com";//replace with **your** info
options.ClientSecret = "abcabcabcabcabcabcabcabc";//replace with **your** info
options.Scopes = new[] { GooglePhotosScope.ReadOnly };
});
}
}
Using appsettings.json is generally the best option however remember the Client ID & Client Secret should be stored securely outside of source control via Azure KeyVault (or .NET Secret Manager as shown below).
dotnet user-secrets init
dotnet user-secrets set "CasCap:GooglePhotosOptions:User" "your.email@mydomain.com" #replace with **your** info
dotnet user-secrets set "CasCap:GooglePhotosOptions:ClientId" "012345678901-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.apps.googleusercontent.com" #replace with **your** info
dotnet user-secrets set "CasCap:GooglePhotosOptions:ClientSecret" "abcabcabcabcabcabcabcabc" #replace with **your** info
After calling AddGooglePhotos in the ConfigureServices method of Startup.cs you can then call upon the GooglePhotosService within your own services shown below.
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;
namespace CasCap.Services
{
public class MyPhotoService
{
readonly ILogger _logger;
readonly GooglePhotosService _googlePhotosSvc;
public MyPhotoService(ILogger<MyPhotoService> logger, GooglePhotosService googlePhotosSvc)
{
_logger = logger;
_googlePhotosSvc = googlePhotosSvc;
}
public async Task Login_And_List_Albums()
{
if (!await _googlePhotosSvc.LoginAsync())
throw new Exception($"login failed");
var albums = await _googlePhotosSvc.GetAlbums();
foreach (var album in albums)
{
_logger.LogInfo($"{album.id}\t{album.title}");
}
}
}
}
If you don't use dependency injection you can new-up the GooglePhotosService manually and pass the mandatory configuration options, logger and HttpClient via the service constructor;
//MyPhotosClass.cs
using CasCap.Models;
using CasCap.Services;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
public class MyPhotosClass
{
public async Task Login_And_List_Albums()
{
//new-up logging
var logger = new LoggerFactory().CreateLogger<GooglePhotosService>();
//new-up configuration options
var options = new GooglePhotosOptions
{
User = "your.email@mydomain.com",//replace with **your** info
ClientId = "012345678901-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.apps.googleusercontent.com",//replace with **your** info
ClientSecret = "abcabcabcabcabcabcabcabc",//replace with **your** info
Scopes = new[] { GooglePhotosScope.ReadOnly },
};
//new-up a single HttpClient
var handler = new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate };
var client = new HttpClient(handler) { BaseAddress = new Uri(options.BaseAddress) };
//new-up the GooglePhotosService and pass in the logger, options and HttpClient
var googlePhotosSvc = new GooglePhotosService(logger, Options.Create(options), client);
//attempt to log-in
if (!await googlePhotosSvc.LoginAsync())
throw new Exception($"login failed!");
//get and list all albums
var albums = await googlePhotosSvc.GetAlbums();
foreach (var album in albums)
{
Console.WriteLine(album.title);
}
}
}
The Google.Apis.Auth library will cache the OAuth 2.0 login information in a local JSON file which it will then read tokens from (and renew if necessary) on subsequent logins. The JSON file(s) are stored on a per-User basis in the Environment.SpecialFolder.ApplicationData folder. On Windows 10 this folder is located at;
If you change the authentication scopes for a User you must delete the JSON file and allow the Google.Apis.Auth library to re-auth and re-create a new JSON file with the new scopes.
You can change the location where these JSON token files are stored at using the FileDataStoreFullPathOverride property in the configuration options;
//Startup.cs
using Microsoft.Extensions.DependencyInjection;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddGooglePhotos(options =>
{
options.User = "your.email@mydomain.com";
options.Scopes = new[] { GooglePhotosScope.ReadOnly };
options.ClientId = "012345678901-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.apps.googleusercontent.com";
options.ClientSecret = "abcabcabcabcabcabcabcabc";
//change FileDataStoreFullPathOverride
options.FileDataStoreFullPathOverride = "c:/temp/GooglePhotos/"
});
}
}
All API functions are exposed by the GooglePhotosService class. There are several sample .NET Core applications which show the basics on how to set-up/config/use the library;
Please post any issues or feedback here.
CasCap.Apis.GooglePhotos is Copyright © 2020 Alex Vincent under the MIT license.