AWSのSDKでS3上のリソースを操作できるが、リソース名を指定し検索してくれる機能がないようです。Spring Cloud AWSのResourceハンドリングを使えば、指定のAntパターンにマッチングするリソースの検索が可能です。
#検証環境
・Spring Boot(Thymeleaf)1.4.3
#必要なライブラリ
...
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-aws-context</artifactId>
<version>1.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-aws-autoconfigure</artifactId>
<version>1.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.11.163</version>
</dependency>
...
#AWS S3に接続するための設定
application.propertiesにアクセスキー、シークレットキー、リージョンを指定する。
また、ローカルからのアクセスであるため、リージョンの自動検知を「false」に指定する。
cloud.aws.credentials.accessKey=AKIAXXXXXXXXXA3Q
cloud.aws.credentials.secretKey=T9JBXXXXXXXXXXXXXXXXXXXXGfLAQ
cloud.aws.region.static=ap-northeast-1
cloud.aws.region.auto=false
上記の設定値を読み込むために、AWSコンフィグクラスを作成する。
@Configuration
public class AWSConfig {
@Value("${cloud.aws.credentials.accessKey}")
private String accessKey;
@Value("${cloud.aws.credentials.secretKey}")
private String secretKey;
@Value("${cloud.aws.region.static}")
private String region;
@Bean
public BasicAWSCredentials basicAWSCredentials() {
return new BasicAWSCredentials(accessKey, secretKey);
}
@Bean
public AmazonS3 amazonS3Client(AWSCredentials awsCredentials) {
return AmazonS3ClientBuilder.standard().withRegion(Regions.fromName(region)).build();
}
}
上記を作成することで、DIコンテナからResourceLoaderとAmazonS3のインスタンスを取得することが可能になります。
#アプリケーションレイヤ
普通のControllerクラスと画面表示用のフォームクラスを作成する。
@RequestMapping(value="/aws/s3/search", method=RequestMethod.POST)
public String search(Model model, S3FileForm fileForm) throws IOException {
S3FileForm s3FileForm = storageService.search(fileForm.getFileName());
model.addAttribute("s3FileForm", s3FileForm);
return "/aws/s3/downloadFromS3";
}
public class S3FileForm implements Serializable {
private String fileName;
private String downloadKey;
private String[] checkedItems;
private List<S3File> fileList;
//...get set省略
}
public class S3File implements Serializable {
private String bucketName;
private String key;
private String contentType;
private Date lastModifiedDate;
//...get set省略
}
#ドメインレイヤ
サービスクラスにてResourcePatternResolver
を使って、Antパターンs3://cinpo/**/*test
にマッチングするリソース名を検索し、対象リソース一覧を取得する。さらに、リソース名でAmazonS3オブジェクトを生成し、最終更新日などのキー情報を取得する。
s3://**/*.txt
を使えばアクセス可能な全バケットを対象に検索が可能です。
/**
* AWS S3操作用サービス
* @author
*
*/
@Service
public class S3StorageService {
private final String BUCKET_NAME = "cinpo";
@Autowired
private ResourceLoader resourceLoader;
@Autowired
private ResourcePatternResolver resourcePatternResolver;
@Autowired
private AmazonS3 amazonS3;
/**
* リソース検索
*
* @param fileName
*/
public S3FileForm search(String fileName) {
// 画面表示用フォーム
S3FileForm s3FileForm = new S3FileForm();
Resource[] resources = null;
try {
// Antパターン(s3://cinpo/**/*test.*)を指定し、対象一覧を取得する。
resources = this.resourcePatternResolver.getResources("s3://" + BUCKET_NAME + "/**/*" + fileName + ".*");
} catch (IOException e) {
throw new RuntimeException(e);
}
List<S3File> s3FileList = new ArrayList<S3File>();
// リソース毎にS3Objectを取得する。
for (Resource resource : resources) {
S3Object s3Object = amazonS3.getObject(new GetObjectRequest("s3.cinpo", resource.getFilename()));
// 画面表示項目の設定
S3File s3File = new S3File();
s3File.setBucketName(s3Object.getBucketName());
s3File.setKey(s3Object.getKey());
s3File.setContentType(s3Object.getObjectMetadata().getContentType());
s3File.setLastModifiedDate(s3Object.getObjectMetadata().getLastModified());
s3FileList.add(s3File);
}
s3FileForm.setFileList(s3FileList);
return s3FileForm;
}
}
#HTML
最後に、検索・一覧表示用の画面を作成する。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<link th:substituteby="common/header :: common_header"/>
<title>S3からファイルダウンロード</title>
</head>
<body>
<h1>File Download</h1>
<p><a href="/index" th:href="@{/index}">Back to home</a></p>
<form action="#" th:action="@{/aws/s3/search}" th:object="${s3FileForm}" method="post">
<table>
<tr>
<td width="100px"><label for="fileName">検索キー</label>:</td>
<td><input type="text" id="fileName" th:field="*{fileName}" size="30px" /></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Search" /></td>
</tr>
</table>
</form>
<div th:if="${s3FileForm.fileList != null}">
<form action="#" th:action="@{/aws/s3/download}" th:object="${s3FileForm}" method="post">
<table border="1">
<tr>
<th width="20px">Download</th>
<th width="10px">Check</th>
<th>Bucket</th>
<th>Key</th>
<th>Content Type</th>
<th>Last Modified Date</th>
</tr>
<tr th:each="file:${s3FileForm.fileList}">
<td>
<button type="submit" name="downloadKey" th:field="*{downloadKey}" th:value="${file.key}">Download</button>
</td>
<td><input type="checkbox" th:field="*{checkedItems}" th:value="${file.key}" /></td>
<td th:text="${file.bucketName}"></td>
<td th:text="${file.key}"></td>
<td th:text="${file.contentType}"></td>
<td th:text="${file.lastModifiedDate}"></td>
</tr>
</table>
<div><input type="submit" value="Download Selected" /></div>
</form>
</div>
</body>
</html>
参考サイド:Spring Cloud AWS