Help us understand the problem. What is going on with this article?

.NET Core のアプリから Google Cloud Storage にアクセスする方法

はじめに

「.NET Core で作成しているWebアプリケーションから、Google Cloud Storage(以下、GCS) にファイルを保存したい」という要件が出てきたときに調べた内容をまとめます。
主な目的はアップロードとダウンロードです。

開発環境

  • Windows 10
  • Visual Studio 2017
  • .NET Core 1.1(諸般の事情で2.x系が使えず...)

準備

  1. GCS でバケットを作成しておく(バケットの名前はあとで使います)
  2. APIの使用を許可するため、Getting Started with AuthenticationCreating a service accountSetting the environment variable を参考に、認証を通しておく
  3. nuget から Google.Cloud.Storage.V1をプロジェクトにインストールする。今回使用したバージョンは 2.1.0-alpha02 です。

バケット情報の取得

Verifying authentication では、認証が成功しているかどうかのチェックのために行われています。

バケット情報の取得
var storage = StorageClient.Create();
var buckets = storage.ListBuckets(projectId);
foreach (var bucket in buckets)
{
    Console.WriteLine(bucket.Name);
}

ファイルのアップロード

ファイルのアップロード・ダウンロードは Utility として使いたかったので、static メソッドとして定義しました。

ファイルのアップロード
/// <summary>
/// ファイルを Google Cloud Storage に保存する
/// </summary>
/// <param name="file">アップロードするファイル</param>
/// <param name="bucketName">バケット名/param>
/// <param name="path">保存先のディレクトリパス</param>
/// <param name="fileName">保存するファイル名</param>
/// <returns></returns>
public static bool SaveFileToGcs(IFormFile file, string bucketName, string path, string fileName)
{
    try
    {
        // Google Storage
        var storage = StorageClient.Create();

        using (var memoryStream = new MemoryStream())
        {
            // ファイルデータを stream にコピー
            file.CopyTo(memoryStream);

            // ストレージにアップロード アップロード先のバケットに path/fileName で保存されます
            storage.UploadObject(bucketName, path + "/" + fileName, file.ContentType,
                memoryStream);
        }
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
        return false;
    }

    return true;
}

ファイルのダウンロード

ファイルのダウンロードはユーザーに保存のアクションをさせたかったので、 返戻値が FileStreamResult 形式になっています。

ファイルのダウンロード
/// <summary>
/// ファイルを Google Cloud Storage からダウンロードしてクライアントに保存させるActionResultを返す
/// </summary>
/// <param name="bucketName">バケット名</param>
/// <param name="targetFileName">保存したファイル名(パス含)</param>
/// <param name="contentType">コンテンツタイプ</param>
/// <returns></returns>
public static FileStreamResult DownloadFileFromGcs(string bucketName, string targetFileName, string contentType)
{
    try
    {
        var storage = StorageClient.Create();
        var memory = new MemoryStream();

        // GCS からダウンロード
        storage.DownloadObject(bucketName, targetFileName, memory);
        memory.Seek(0, SeekOrigin.Begin);

        return new FileStreamResult(memory, contentType);
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
        return null;
    }

}

おまけ:文字列をファイルにして GCS に保存する

jsonを文字列として渡されて、GCSに保存してほしい!という要件も追加できたので、文字列からファイルを作ってそのまま GCS に保存するメソッドも追加しました。

文字列から保存
/// <summary>
/// 文字列を指定されたファイル名で Google Cloud Storage に保存する
/// </summary>
/// <param name="content">ファイルとして保存する内容</param>
/// <param name="bucketName">バケット名</param>
/// <param name="path">保存先のパス</param>
/// <param name="fileName">保存ファイル名</param>
/// <param name="contentType">コンテンツタイプ</param>
/// <param name="encoding">エンコード</param>
/// <returns></returns>
public static bool SaveFileToGcs(string content, string bucketName, string path, string fileName, string contentType, Encoding encoding)
{
    try
    {
        // Google Storage
        var storage = StorageClient.Create();

        using (var memoryStream = new MemoryStream())
        using (var writer = new StreamWriter(memoryStream, Encoding.UTF8))
        {
            writer.WriteAsync(content);

            writer.Flush();
            memoryStream.Seek(0, SeekOrigin.Begin);

            // ストレージにアップロード
            storage.UploadObject(bucketName, path + "/" + fileName, contentType, memoryStream);
        }

    }
    catch (Exception e)
    {
        Debug.Fail(e.Message);
        return false;
    }

    return true;
}

さいごに

nuget でパッケージをいれれば特に面倒な設定とかもなく、さくっと使えて、思ってたより簡単にできました。
GCPで.NET Core で、ていうのはまだ記事は少ないような感じがします。特に日本語。
でも、どちらも公式のドキュメントがしっかりしていて、非常にやりやすいです。設計も使い勝手もわかりやすい!

さて、これからも GCP と .NET Core をどんどん使っていきますよー!

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした