はじめに
「.NET Core で作成しているWebアプリケーションから、Google Cloud Storage(以下、GCS) にファイルを保存したい」という要件が出てきたときに調べた内容をまとめます。
主な目的はアップロードとダウンロードです。
開発環境
- Windows 10
- Visual Studio 2017
- .NET Core 1.1(諸般の事情で2.x系が使えず...)
準備
- GCS でバケットを作成しておく(バケットの名前はあとで使います)
- APIの使用を許可するため、Getting Started with Authentication の Creating a service account と Setting the environment variable を参考に、認証を通しておく
- 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 をどんどん使っていきますよー!