Spring BootでAWS S3に接続

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

Spring Bootでは日常的に触れているAWSに接続できる方法があるということで調べてみました。
まずはS3です。

環境

Mac OSX 10.10.5 Yosemite
Java 8
Spring Boot 1.3.5

機能

・S3からローカルにファイルをダウンロード
・S3へローカルからファイルをアップロード
・S3内のオブジェクトを検索

コード

設定ファイル

gradle

buildscript {
	ext {
		springBootVersion = '1.3.5.RELEASE'
	}
	repositories {
		mavenCentral()
	}
	dependencies {
		classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 
	}
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'spring-boot' 

jar {
	baseName = 'demo'
	version = '0.0.1-SNAPSHOT'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
	mavenCentral()
}


dependencies {
	compile('org.springframework.boot:spring-boot-starter-web:1.3.5.RELEASE')
	compile('org.springframework.cloud:spring-cloud-starter-aws')
	compile('org.springframework.cloud:spring-cloud-aws-context')
	testCompile('org.springframework.boot:spring-boot-starter-test') 
}

dependencyManagement {
	imports { 
		mavenBom "org.springframework.cloud:spring-cloud-dependencies:Brixton.SR1" 
	}
}


eclipse {
	classpath {
		 containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER')
	}
}

application.yml

cloud.aws:
  credentials:
    accessKey: "aws_access_key"
    secretKey: "aws_secret_access_key"
  region:
    static: "リージョン"

S3の接続情報を記述します。
ファイル自体は、「src/main/resources」以下にフォルダ「config」を作成して入れます。

起動クラス

Spring Bootを走らせるだけです。

package com.test.aws;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class AwsS3Application {

	public static void main(String[] args) {
	  SpringApplication.run(AwsS3Application.class, args);
	}

}

コントローラー

package com.test.aws;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.WritableResource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RequestMapping("/s3")
public class S3Controller {

	@Autowired
	private ResourceLoader resourceLoader;
	

24行目、基本のURLを「http://localhost:8080/s3」に設定。
27〜28行目、ResourceLoaderを@Autowierd。これでS3と接続します。

	@RequestMapping(value="/download", method=RequestMethod.GET)
	public void download(@RequestParam String filename) throws IOException {
		Resource resource = this.resourceLoader.getResource("s3://バケット名/" + filename);
		InputStream input = resource.getInputStream();
		BufferedReader reader = new BufferedReader(new InputStreamReader(input));
		String str = new String();
		StringBuilder builder = new StringBuilder();
		while ((str = reader.readLine()) != null) {
			builder.append(str);
		};

		File file = new File("ダウンロードファイルを置くURL/ファイル名");
		FileWriter writer = new FileWriter(file);
		writer.write(builder.toString());
		
		writer.close();
		reader.close();
		input.close();
	}
	

30〜51行目、ダウンロードするメソッドです。
30行目、基本のURLに「/download」でこのメソッドに繋がります。
31行目、接続するバケットとダウンロードするファイルを設定。
33〜39行目、取得したファイルから文字列を取得。
41〜43行目、ダウンロードしたファイルの配置場所とファイル名を設定し、文字を書き込みます。
45〜47行目、終了処理。

	
	@RequestMapping(value="/upload", method=RequestMethod.GET)
	public void upload(@RequestParam String filename) throws IOException {
		File file = new File("アップロードするファイルのディレクトリ" + filename);
		FileInputStream input = new FileInputStream(file);
		BufferedReader reader = new BufferedReader(new InputStreamReader(input));
		String str = new String();
		StringBuilder builder = new StringBuilder();
		while ((str = reader.readLine()) != null) {
			builder.append(str);
		};

		Resource resource = this.resourceLoader.getResource("s3://バケット名/" + filename");
		WritableResource writableResource = (WritableResource) resource;
		try (OutputStream output = writableResource.getOutputStream();) {
			output.write(builder.toString().getBytes());
		}
	}

50行目、基本のURLに「/upload」でこのメソッドに繋がります。
51行目、引数に@RequestParamを設定しているので、URLに「?filename=text.txt」などで値を渡せます。
52行目、アップロードするファイルを指定します。51行目の引数を使うと良いです。
53〜59行目、ファイルから文字列を取得。
61行目、アップロードするバケットとファイル名を設定。ファイル名はアップロード元と合わせなくても大丈夫です。
62〜65行目、取得した文字列を書き込みます。

	@Autowired
	private ResourcePatternResolver resolver;
		
	@RequestMapping(value="/search", method=RequestMethod.GET)
	public String search() throws IOException {
		Resource[] resources = this.resolver.getResources("s3://バケット名/**/*.txt");
		StringBuilder builder = new StringBuilder();
		for (int i = 0; i < resources.length; i++) {
			if (i!=0) {
				builder.append(", ");
			}
			builder.append(resources[i].toString());
		}
		
		return builder.toString();
	}
	
}

68〜69行目、ResourcePatternResolverを繋げます。
71〜83行目、アップロードするメソッドです。バケット内の「.txt」を検索して出力します。
71行目、基本のURLに「/search」でこのメソッドに繋がります。
73行目、探したいファイルを指定。「*」でlike検索が可能です。
74〜80行目、検索結果をStringBuilderに追加し、
82行目、検索を返します。

実行

下記のコマンドで結果を取得できます。

$ curl http://localhost:8080/s3/upload?filename=ファイル名
$ curl http://localhost:8080/s3/download?filename=ファイル名
$ curl http://localhost:8080/s3/search

さいごに

簡単に接続できました。
他のサービスとの接続も試してみたいと思います。