[C#][Azure Functions]Google Drive Api(v3)でフォルダ&スプレッド作成

C# C#

この記事では、Azure FunctionsからGoogle Drive Apiを使ってService Account経由でスプレッドシートとフォルダ作成をしています。

フォルダ作成はDrive Apiでわかるのですが、スプレッドシート作成にもGoogle Drive apiを使う必要がありました…
ドライブのファイル作成だから…といえばそうなのかもですが

Service Accountだとブラウザ認証がいらないかわりに、サービスアカウントに共有しているフォルダやシートにしか更新ができないようだったので、その点が注意が必要です。

Service Accountの設定

Service Accountを作成する

google developer consoleでprojectを作成した後に、サービスアカウントを作ります。

認証情報を作成からサービスアカウントを選択します。

サービスアカウントの作成画面に適当な名前などを設定します。

次へを押して、プロジェクトへのアクセス権の設定に移ります。とりあえずそのままで問題ないです。

とりあえず動かしたいだけなので、ユーザーへのアクセス権のところもそのままで、問題ないです。

サービスアカウントができるので、リンクから詳細画面に遷移します。

詳細画面で鍵の追加をクリックして、「新しい鍵を作成」を押して新しい鍵をJSONで作成します。

鍵を作成すると、ファイルとしてダウンロードされるので(JSON)、大事に保存しておきます😄
このファイルを認証に使うので、プロジェクトに追加して、常にコピーするようにオプションで設定します。

今回のサンプルでは、service-account-key.jsonという名前で使っています。

親のフォルダ設定

サービスアカウントではアクセスする際に共有している場所でないと、フォルダの作成などができないので共有設定をしておきます。

共有を押すと、メールアドレスを入れることになるので、サービスアカウントのメールアドレスを入力します!

Service Accountを使ってスプレッドシートとフォルダを作成する

Google Drive Apiを導入する

Google Drive Apiを使うために、Nugetからライブラリを導入します。
Nugetパッケージ管理 > Google.Api.Drive.v3を検索してパッケージの追加をします。

サンプルコード

必要そうな箇所のコードだけまるっと持ってきてみました。

using System;
using System.Collections.Generic;
using System.IO;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Drive.v3;
using Google.Apis.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Data = Google.Apis.Sheets.v4.Data;

namespace poc_azure_function.Controllers
{
    public class SpreadSheetServiceAccountController
    {
        private DriveService _driveService;
        public string _parentFolderId = "{parentFolderId}";

        /// <summary>
        /// Service AccountでGoogle Drive にアクセスするためのDriveServiceを返す。
        /// </summary>
        /// <returns></returns>
        private DriveService ConnectDriveService()
        {
            GoogleCredential credential;
            string[] scopes = { DriveService.Scope.Drive };
            using (var stream = new FileStream("service-account-key.json", FileMode.Open, FileAccess.Read))
            {
                credential = GoogleCredential.FromStream(stream).CreateScoped(scopes);
            }
            return new DriveService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = "codelike drive connect",
            });
        }

        /// <summary>
        /// Google Drive Apiフォルダ作成
        /// </summary>
        [FunctionName("SaCreateFolder")]
        public IActionResult CreateFolder(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "sa_create_folder")] HttpRequest req, ILogger log)
        {
            _driveService = ConnectDriveService();

            Google.Apis.Drive.v3.Data.File meta = new Google.Apis.Drive.v3.Data.File();
            meta.Name = "folderName";
            meta.Description = "folder description";
            meta.MimeType = "application/vnd.google-apps.folder";

            // 親ディレクトリはService Accountのメールアドレスを入れて共有する
            meta.Parents = new List<string> { _parentFolderId };

            var request = _driveService.Files.Create(meta);
            request.Fields = "id";
            var response = request.Execute();

            return new ObjectResult(JsonConvert.SerializeObject(response.Id));
        }


        /// <summary>
        /// Service AccountでSpread Sheetを作成する
        /// </summary>
        /// <param name="req"></param>
        /// <param name="log"></param>
        /// <returns></returns>
        [FunctionName("SaSpreadCreate")]
        public IActionResult SpreadCreate(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "sa_spread_create")] HttpRequest req, ILogger log)
        {
            _driveService = ConnectDriveService();

            Google.Apis.Drive.v3.Data.File meta = new Google.Apis.Drive.v3.Data.File
            {
                Name = "SheetName",
                Description = "SpreadSheetDescription",
                MimeType = "application/vnd.google-apps.spreadsheet",
                Parents = new List<string> { _parentFolderId }
            };
            var request = _driveService.Files.Create(meta);
            var response = request.Execute();

            return new ObjectResult(JsonConvert.SerializeObject(response.Id));
        }
    }
}

コード解説

Service Accountの認証箇所

28行目からのConnectDriveServiceメソッドでGoogle Driveにservice-account-key.jsonで接続に行って、
ドライブの操作をするためのオブジェクト(DriveService)を返しています。

フォルダ作成API

フォルダを作成する場合は http://localhost:7071/api/sa_create_folder にアクセスすると、新しいフォルダが作成されるようにFunctionsのURLを設定しています。(46行目)

47-63行目がアクセスされた時の処理ですが、
やっていることは、48行目でApiアクセスのためのDriveServiceを作って、

50-53行目でフォルダの情報を作って、親ディレクトリを指定して作っておいたDriveServiceにフォルダの情報を渡して、実行しています。
Nameがフォルダ名で、Descriptionが説明文(詳細情報に出ます)になります。

MimeTypeを”application/vnd.google-apps.folder”にしているのがポイントで、これでフォルダが作成されます。

親ディレクトリ(Parents)を指定するときのIDは共有設定をしたディレクトリになります。
共有設定をしたディレクトリのURLを参照すると、

drive.google.com/drive/u/0/folders/xxxxxxxxxxxx

みたいな感じになっていると思うので、ここのxxxxxxx…の値を使います。

シート作成API

やっていることはほとんど、上記のフォルダ作成APIと同じです。
シートを作成する場合は http://localhost:7071/api/sa_spread_create にアクセスすると、作られるようにFunctionsの設定をしています。(74行目)

75-88行目が処理になりますが、同じようにDriveServiceを作って、作成されるファイルの情報を渡して実行しています。
Nameがシート名で、Descriptionが説明文(シートの詳細情報とかに出ます)になります。

あとは同じように権限のある親ディレクトリ(Parents)を指定するのと、MimeTypeを”application/vnd.google-apps.spreadsheet”にするのがポイントです。

今気づきましたが、ほとんど同じ処理なのに書き方がばらついてるので直した方が良さそうですね…

動作確認

VSからプログラムを起動して…

スプレッドシート作成APIにアクセスします。

フォルダ作成APIにアクセスします。

フォルダとシートができました😄

github

コメント

タイトルとURLをコピーしました