.NET 5, F# - Google Drive API Quickstart +α

commits12 min read読了の目安(約11400字

概要

.NET 5、F# で Google Drive API 入門。

事前準備

  1. Drive API が有効な Google Cloud Platform のプロジェクトを用意する [↗]
  2. credentials.json を作る [↗]

環境

プロジェクトの構成

プロジェクトを作成する

dotnet new console -lang "F#" -o 場所\プロジェクト名

ライブラリを追加する

Visual Studio Code で作成したプロジェクトを開き、ターミナル (Ctrl + `) で下記のコマンドを実行。

dotnet add package Google.Apis.Drive.v3

credentials.json を利用できるようにする

プロジェクトフォルダの直下に credentials.json を配置。

  プロジェクト
   ├─ プロジェクト.fsproj
   ├─ Program.fs
+  └─ credentials.json

.fsprojcredentials.jsonbin\Debug\net5.0 にコピーする設定を追記する。

.fsproj
    <ItemGroup>
+     <Content Include="credentials.json">
+       <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+     </Content>
      <Compile Include="Program.fs" />
    </ItemGroup>

Program.fs を変更する

.NET quickstart (C#) [↗] を改変したプログラムです。
変数 driveService から Google Drive API の機能を呼び出します。

Program.fs
let Scopes = [|
    Google.Apis.Drive.v3.DriveService.Scope.Drive
|]

let ApplicationName = "Drive API F# Quickstart"

let fileStream = new System.IO.FileStream("credentials.json", System.IO.FileMode.Open, System.IO.FileAccess.Read)
let clientSecrets = Google.Apis.Auth.OAuth2.GoogleClientSecrets.Load(fileStream).Secrets
fileStream.Dispose()
let cancellationToken = System.Threading.CancellationToken.None
let fileDataStore = new Google.Apis.Util.Store.FileDataStore("token.json", true)
let userCredential = Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.AuthorizeAsync(clientSecrets, Scopes, "user", cancellationToken, fileDataStore).Result

let initializer = new Google.Apis.Services.BaseClientService.Initializer()
initializer.ApplicationName <- ApplicationName
initializer.HttpClientInitializer <- userCredential

let driveService = new Google.Apis.Drive.v3.DriveService(initializer)

Scopes

プログラムが利用する機能 (値の一覧 [↗])。

Google Drive

Google Drive API を使う上で必要になる知識。

ID

Google Drive [↗] の「リンクを取得」から確認できます。

種類 ID
ファイル https://drive.google.com/file/d/ ココ /view?usp=sharing
フォルダ https://drive.google.com/drive/folders/ ココ ?usp=sharing
マイドライブ root

Google.Apis.Drive.v3

ファイル・フォルダの取得

let getRequest = driveService.Files.Get("対象の ID")
// ...
let itemData = getRequest.Execute()

-- 取得する情報の設定

getRequest.Fields <- "nextPageToken, files(name, id)"
printfn "%s" itemData.Name
printfn "%s" itemData.Id

ファイル・フォルダの検索

let listRequest = driveService.Files.List()
// ...
let itemList = listRequest.Execute()

-- 検索の条件

listRequest.Q <- "('root' in parents) and (trashed = false)"

ファイル限定

listRequest.Q <- "mimeType != 'application/vnd.google-apps.folder'"

フォルダ限定

listRequest.Q <- "mimeType = 'application/vnd.google-apps.folder'"

-- 取得する情報の設定

listRequest.Fields <- "nextPageToken, files(name, id)"
let listRequest = driveService.Files.List()
listRequest.Fields <- "nextPageToken, files(name, id)"
let itemList = listRequest.Execute()
let itemData = itemList.Files.[0]

printfn "%s" itemData.Name
printfn "%s" itemData.Id

-- 1ページあたりのファイル・フォルダ数

  • 規定値: 100
  • 最大値: 1000
listRequest.pageSize <- 1

-- 取得されるページの管理

  • PageToken: 検索するページ
  • nextPageToken: 次のページを表す文字列
let listRequest = driveService.Files.List()
listRequest.Fields <- "nextPageToken, files(name, id)"
let mutable itemList = listRequest.Execute()

while itemList.NextPageToken <> null do
    let listRequest = driveService.Files.List()
    listRequest.Fields <- "nextPageToken, files(name, id)"
    listRequest.PageToken <- itemList.NextPageToken
    itemList <- listRequest.Execute()

フォルダの作成

let metadata = new Google.Apis.Drive.v3.Data.File()
metadata.Name <- "フォルダ名"
metadata.MimeType <- "application/vnd.google-apps.folder"
metadata.Parents <- [|"親フォルダの ID"|]

let createRequest = driveService.Files.Create(metadata)
createRequest.Execute() |> ignore

ファイルのアップロード

関数 GetMimeMapping の定義は 下部に記載

let filePath = @"ローカルファイルのパス"

let metadata = new Google.Apis.Drive.v3.Data.File()
metadata.Name <- System.IO.Path.GetFileName filePath
metadata.Parents <- [|"親フォルダの ID"|]

let fileStream = new System.IO.FileStream(filePath, System.IO.FileMode.Open)
let createMediaUpload = driveService.Files.Create(metadata, fileStream, GetMimeMapping filePath)
createMediaUpload.Upload() |> ignore
fileStream.Dispose()

-- アップロードしたファイルの ID を取得

明示的に ID を生成する。

let generateIdsRequest = driveService.Files.GenerateIds()
generateIdsRequest.Count <- 1
let id = generateIdsRequest.Execute().Ids.[0]

let metadata = new Google.Apis.Drive.v3.Data.File()
metadata.Id <- id
// ...
let iUploadProgress = createMediaUpload.Upload()
if iUploadProgress.Status = Google.Apis.Upload.UploadStatus.Failed then
    raise iUploadProgress.Exception

ファイルのダウンロード

let getRequest = driveService.Files.Get "ファイルの ID"
let filePath = System.IO.Path.Combine(@"保存先のフォルダパス", "ファイル名")

let fileStream = new System.IO.FileStream(filePath, System.IO.FileMode.Create, System.IO.FileAccess.Write)
getRequest.Download(fileStream)
fileStream.Dispose()

名前の変更

let metadata = new Google.Apis.Drive.v3.Data.File()
metadata.Name <- "新しい名前"
let UpdateRequest = driveService.Files.Update(metadata, "対象の ID")
UpdateRequest.Execute() |> ignore

ファイルの更新

関数 GetMimeMapping の定義は 下部に記載

let filePath = @"ファイルのパス"

let metadata = new Google.Apis.Drive.v3.Data.File()
metadata.Name <- System.IO.Path.GetFileName filePath
let mimeMapping = GetMimeMapping filePath
metadata.MimeType <- mimeMapping

let fileStream = new System.IO.FileStream(filePath, System.IO.FileMode.Open)
let updateMediaUpload = driveService.Files.Update(metadata, "ファイルの ID", fileStream, mimeMapping)
updateMediaUpload.Upload() |> ignore
fileStream.Dispose()

ファイルの複製

let metadata = new Google.Apis.Drive.v3.Data.File()
metadata.Parents <- [|"親フォルダの ID"|]
let copyRequest = driveService.Files.Copy(metadata, "ファイルの ID")
let itemData = copyRequest.Execute()

ファイル・フォルダの移動

let metadata = new Google.Apis.Drive.v3.Data.File()
let updateRequest = driveService.Files.Update(metadata, "対象の ID")
updateRequest.AddParents <- "移動前のフォルダの ID"
updateRequest.RemoveParents <- "移動先のフォルダの ID"
updateRequest.Execute() |> ignore

ファイル・フォルダの削除

let deleteRequest = driveService.Files.Delete("対象の ID")
deleteRequest.Execute() |> ignore

補足: .NET 5 での MIME タイプの取得

関連項目

記述時点でのメソッド対応状況

利用 メソッド
× System.Web.MimeMapping.GetMimeMapping
Microsoft.Win32.Registry.ClassesRoot.OpenSubKey

Microsoft.Win32.RegistryNuGet で提供されている [↗] のでそちらを使います。

実装

dotnet add package Microsoft.Win32.Registry
let GetMimeMapping (filePath: string) =
    let mutable mimeMapping = "application/octet-stream"
    let ext = System.IO.Path.GetExtension(filePath).ToLower()
    let registryKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey ext

    if registryKey <> null then
        let mimeType = registryKey.GetValue "Content Type"
        if mimeType <> null then
            mimeMapping <- mimeType.ToString()

    mimeMapping

end