以前、JavaでSpring Bootフレームワークを利用してファイルをアップロードするプログラムを作成したことがあったが、ファイルのアップロード先をAzure Blob Storageのコンテナー内に設定することもできる。
今回は、App Service上でAzure Blob Storageのコンテナー内にファイルをアップロードするプログラムを作成してみたので、共有する。
前提条件
下記記事のBlob Storageの作成が完了していること。
また、下記記事の実装が完了していること。
Azure Storageへのアクセスキー、Blobコンテナー名の確認
Azure Storageにアクセスするプログラム内では、アカウント名・アクセスキー・コンテナー名を設定する必要があるが、その設定内容はAzure Portal上で確認できる。その手順は、以下の通り。
1) Azure Portalにログイン後、作成したAzure Storageを表示し、「アクセスキー」メニューを押下後、「キーの表示」を押下する。

2) 以下のように、アクセスキーが表示される。このうち「key1」の「キー」をアクセスキーとする。

3) 「概要」メニューを表示した後で、「コンテナー」メニューを押下する。

4) 以下のように、「blobcontainer」というコンテナーがあることが確認できる。

作成したサンプルプログラム(App Service側)の内容
作成したサンプルプログラム(App Service側)の構成は以下の通り。なお、Azure Functions側のソースコードは修正していない。

なお、上記の赤枠は、前提条件のプログラムから追加・変更したプログラムである。
pom.xmlの内容は以下の通りで、Azure Storageにアクセスするための設定を追加している。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.0</version>
<relativePath/>
<!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demoAzureApp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>demoAzureApp</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- lombokの設定 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!-- Azure Storageの設定 -->
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-storage</artifactId>
<version>8.3.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-webapp-maven-plugin</artifactId>
<version>1.12.0</version>
<configuration>
<schemaVersion>v2</schemaVersion>
<subscriptionId>(ログインユーザーのサブスクリプションID)</subscriptionId>
<resourceGroup>azureAppDemo</resourceGroup>
<appName>azureAppDemoService</appName>
<pricingTier>B1</pricingTier>
<region>japaneast</region>
<appServicePlanName>ASP-azureAppDemo-8679</appServicePlanName>
<appServicePlanResourceGroup>azureAppDemo</appServicePlanResourceGroup>
<runtime>
<os>Linux</os>
<javaVersion>Java 8</javaVersion>
<webContainer>Tomcat 8.5</webContainer>
</runtime>
<deployment>
<resources>
<resource>
<directory>${project.basedir}/target</directory>
<includes>
<include>*.war</include>
</includes>
</resource>
</resources>
</deployment>
</configuration>
</plugin>
</plugins>
</build>
</project>application.propertiesの内容は以下の通りで、Azure Storageにアクセスするためのアカウント名・アクセスキー・コンテナー名を追加している。

コントローラクラスの内容は以下の通りで、アップロードボタンが押下されたときに、Blobコンテナーにアップロードしたファイルを格納する処理を追加している。
package com.example.demo;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.thymeleaf.util.StringUtils;
import com.microsoft.azure.storage.CloudStorageAccount;
import com.microsoft.azure.storage.blob.BlobOutputStream;
import com.microsoft.azure.storage.blob.CloudBlobClient;
import com.microsoft.azure.storage.blob.CloudBlobContainer;
import com.microsoft.azure.storage.blob.CloudBlockBlob;
@Controller
public class DemoController {
/** Azure Storageのアカウント名 */
@Value("${azure.storage.accountName}")
private String storageAccountName;
/** Azure Storageへのアクセスキー */
@Value("${azure.storage.accessKey}")
private String storageAccessKey;
/** Azure StorageのBlobコンテナー名 */
@Value("${azure.storage.containerName}")
private String storageContainerName;
/**
* メイン画面を初期表示する.
* @param model Modelオブジェクト
* @return メイン画面
*/
@GetMapping("/")
public String index(Model model) {
model.addAttribute("message"
, "アップロードするファイルを指定し、アップロードボタンを押下してください。");
return "main";
}
/**
* ファイルデータをAzure Blob Storageに登録する.
* @param uploadFile アップロードファイル
* @param model Modelオブジェクト
* @return メイン画面
*/
@PostMapping("/upload")
public String add(@RequestParam("upload_file") MultipartFile uploadFile
, Model model) {
// ファイルが未指定の場合はエラーとする
if (uploadFile == null
|| StringUtils.isEmptyOrWhitespace(uploadFile.getOriginalFilename())) {
model.addAttribute("errMessage", "ファイルを指定してください。");
return "main";
}
// ファイルアップロード処理
try {
// Blobストレージへの接続文字列
String storageConnectionString = "DefaultEndpointsProtocol=https;"
+ "AccountName=" + storageAccountName + ";"
+ "AccountKey=" + storageAccessKey + ";";
// ストレージアカウントオブジェクトを取得
CloudStorageAccount storageAccount
= CloudStorageAccount.parse(storageConnectionString);
// Blobクライアントオブジェクトを取得
CloudBlobClient blobClient = storageAccount.createCloudBlobClient();
// Blob内のコンテナーを取得
CloudBlobContainer container
= blobClient.getContainerReference(storageContainerName);
// Blob内のコンテナーにデータを書き込む
CloudBlockBlob blob
= container.getBlockBlobReference(uploadFile.getOriginalFilename());
BlobOutputStream output = blob.openOutputStream();
output.write(IOUtils.toByteArray(uploadFile.getInputStream()));
output.close();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
// メイン画面へ遷移
model.addAttribute("message", "ファイルアップロードが完了しました。");
return "main";
}
}メイン画面のHTMLファイルの内容は以下の通りで、ファイルのアップロードを行う画面となっている。
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>メイン画面</title>
</head>
<body>
<form method="post" enctype="multipart/form-data" th:action="@{/upload}">
<th:block th:if="!${#strings.isEmpty(message)}">
<span th:text="${message}">メッセージ</span><br/><br/>
</th:block>
<th:block th:if="!${#strings.isEmpty(errMessage)}">
<font color="#FF0000">
<span th:text="${errMessage}">エラーメッセージ</span>
</font><br/><br/>
</th:block>
ファイル : <input type="file" name="upload_file" /><br/><br/>
<input type="submit" value="アップロード" />
</form>
</body>
</html>その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/azure/tree/master/azure-blob-storage-upload/demoAzureApp
作成したサンプルプログラムの実行結果
サンプルプログラムをAzure App Serviceにデプロイして実行した結果は、以下の通り。
1) サンプルプログラム実行前のBlobコンテナーの内容は以下の通りで、ファイルがアップロードされていないことが確認できる。

2) Azure App ServiceのURL「https://azureappdemoservice.azurewebsites.net/」とアクセスし、「ファイルの選択」ボタンが押下する。

なお、上記URLは、下記Azure App ServiceのURLから確認できる。

3) アップロードファイルを選択し、「開く」ボタンを押下する。

4) 指定したファイルが選択された状態になっていることを確認後、「アップロード」ボタンを押下する。

5) アップロードが完了し、完了メッセージが表示されることが確認できる。

6) サンプルプログラム実行後、以下のように、アップロードしたファイルが配置されていることが確認できる。

要点まとめ
- JavaでSpring Bootフレームワークを利用してファイルをアップロードするプログラムのファイルアップロード先は、Azure Blob Storageのコンテナー内に設定することができる。





