Java on Azure 実践開発【Blob Upload ③: 定期アップロード編】

## はじめに

本記事は、『Java on Azure 実践開発 Blob Upload』シリーズの第3回「定期アップロード」編です。
サンプルコードは、[kohei3110/JavaOnAzure-BlobStorage](https://github.com/kohei3110/JavaOnAzure-BlobStorage) に上がっています。

## シナリオ概説

本シリーズでは、Blob Storage へのファイルアップロードについて、Azure を使った Java アプリケーションのサンプルコードを使用しながら、開発方法をご紹介します。

一口にファイルアップロードといっても、あらゆる方式があるかと思います。例えば、以下のようなものがあります。

| No. | シナリオ |  概要 | 記事 URL |
| :--- | :--- | :--- | :--- |
| 1 | サーバー経由でのストリームライクなアップロード | SAS の流出を懸念する場合、サーバー経由でのストリームライクなアップロード | [Java on Azure 実践開発【Blob Upload ①: ストリームライクなアップロード編】](https://qiita.com/kk31108424/items/63ab4fdd0492e344573a) |
| 2 | サーバーに一時保存後アップロード | アプリケーションサーバーのローカルストレージにファイルを一度保存後、アップロード（クライアントからは同期に見える） | [Java on Azure 実践開発【Blob Upload ②: App Service ローカル保存後アップロード編】](https://qiita.com/kk31108424/items/366649945294a50b808a) |
| 3 | サーバーに一時保存後定期アップロード | アプリケーションサーバーのローカルストレージにファイルを一度保存後、**定期ジョブにて**アップロード（クライアントからは非同期に見える） | [Java on Azure 実践開発【Blob Upload ③: 定期アップロード編】](https://qiita.com/kk31108424/items/5182adf18695238fc1e1) |
| 4 | 署名付き URL を使ったアップロード | アプリケーションから返却された署名付き URL を用いて、クライアントからファイルをアップロードする | [Java on Azure 実践開発【Blob Upload ④: 署名付き URL を使ったアップロード編】](https://qiita.com/kk31108424/items/314027635b4518b2a6b2) |

本記事では、<b>『3. 定期アップロード』</b>について実装上のポイントを解説していきます。

## 実装内容

クライアントからリクエストされたアップロード対象のファイルを、App Service のローカルファイルシステムに一時保存します。保存が完了したら、クライアントに `OK(200)` を返却します。

App Service が実行されている App Service Plan の上で、最終更新日時が1分以内のファイルをアップロードする定期ジョブが別インスタンスとして実行されます。このジョブを、今回は Web Jobs にて実装しています。

この Web Jobs は、1 時間に 1 回、アップロード対象のファイルを削除するジョブも実行します。これにより、アップロードされたファイルが App Service Plan のファイルシステムから削除されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/019c77c2-2f4d-ad6d-c57b-3fe094096839.png)

## 実装に必要なクラス

ここからは、実装する際に必要となるクラスについて解説していきます。

### BlobAsyncClient クラス

`BlobAsyncClient` クラスは、Blob Storage の各オブジェクト（Blob）操作をするためのクライアントを提供します。`BlobAsyncClient` クラスにより、Blob アップロードやダウンロード、Blob のコピーなどの操作が可能になります。

`BlobAsyncClient` は、`BlobClientBuilder` でインスタンス化するか、`getBlobAsyncClient()`メソッドで取得することができます。

なお、Azure では以下３種類の Blob をサポートしています。今回は、ファイルアップロード用途なので、ブロック Blob を使用しました。
これらに対応するクライアントも、Azure SDK for Java で用意されています。
| Blob 種類 | 概要 | クライアント取得メソッド | Javadoc |
| :--- | :--- | :--- | :--- |
|ブロック BLOB | 大量のデータを効率的にアップロードするためのに最適。| [BlobAsyncClient.getBlockBlobAsyncClient Method](https://docs.microsoft.com/ja-jp/java/api/com.azure.storage.blob.blobasyncclient.getblockblobasyncclient?view=azure-java-stable)| [getBlockBlobAsyncClient()](https://javadoc.io/static/com.azure/azure-storage-blob/12.0.0-preview.4/com/azure/storage/blob/BlobAsyncClient.html#getBlockBlobAsyncClient--) |
| 追加 BLOB | 追加操作（仮想マシンのデータのログ記録などのシナリオ）に最適。| [BlobAsyncClient.getAppendBlobAsyncClient Method](https://docs.microsoft.com/ja-jp/java/api/com.azure.storage.blob.blobasyncclient.getappendblobasyncclient?view=azure-java-stable) | [getAppendBlobAsyncClient()](https://javadoc.io/static/com.azure/azure-storage-blob/12.0.0-preview.4/com/azure/storage/blob/BlobAsyncClient.html#getAppendBlobAsyncClient--) | 
| ページ BLOB | ランダムな読み取りと書き込みの操作用に最適。| [BlobAsyncClient.getPageBlobAsyncClient Method](https://docs.microsoft.com/ja-jp/java/api/com.azure.storage.blob.blobasyncclient.getpageblobasyncclient?view=azure-java-stable) | [getPageBlobAsyncClient()](https://javadoc.io/static/com.azure/azure-storage-blob/12.0.0-preview.4/com/azure/storage/blob/BlobAsyncClient.html#getPageBlobAsyncClient--) |

参考: 『[BlobAsyncClient Class](https://docs.microsoft.com/en-us/java/api/com.azure.storage.blob.blobasyncclient?view=azure-java-stable)』
JavaDoc: 『[Class BlobAsyncClient](https://azuresdkartifacts.blob.core.windows.net/azure-sdk-for-java/staging/apidocs/com/azure/storage/blob/BlobAsyncClient.html)』

```java:UploadBlobStreamRepository.java
・・・
            BlobAsyncClient blobAsyncClient = new BlobClientBuilder()
                .connectionString(connectionString)
                .containerName(CONTAINER_NAME)
                .blobName(blobName)
                .buildAsyncClient();
・・・
```

## Tips

実装上の Tips をご紹介します。

### Web Jobs のアップロード方法

Azure WebJobsとは、Azureにて、crontabで定義するような定期処理または、デーモンプロセスのようなものを起動するための仕組みです。

デプロイには、以下の作業が必要です。

１）コンパイルし、jar ファイルにパッケージング
２）実行用のバッチファイル（`run.cmd`を作成）

```powershell:run.cmd
set PATH=%PATH%;%JAVA_HOME%/bin
java -jar webjob-0.0.1-SNAPSHOT.jar
```

今回は、jar ファイルとバッチファイルの2つをzip化し、Azure Portal から WebJobs のデプロイを行いました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/7d976e90-bf61-0085-7244-5ff9eb79441b.png)

### App Service Plan でのインスタンスを跨いだストレージの参照

今回は、一つの App Service Plan に複数の App Service インスタンス（App Service / WebJobs）をデプロイしています。

App Service インスタンス間で共有ドライブを参照し、そのドライブに存在するファイルを操作するため、`%HOME%` 配下をマウントする構成としています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/383cf5c1-cc6c-c8d2-196b-353345bb6cb4.png)

App Service Plan のファイルシステムの構成は、以下サイトが詳しいです。

GitHub: [Understanding the Azure App Service file system](https://github.com/projectkudu/kudu/wiki/Understanding-the-Azure-App-Service-file-system)

## おわりに

本記事は、『Java on Azure 実践開発 Blob Upload 編】③』として、アプリケーション実行環境のローカルストレージに保存後、定期ジョブにてファイルをアップロードする方法についてまとめました。

次回は、アプリケーションから返却された期限付き URL を用いて、クライアントからファイルをアップロードする方法についてまとめていきます！お楽しみに～。