Spring BootでS3からファイルをダウンロードする方法




Spring Bootで使用するプラグイン設定

S3へのアップロードは下記を参照してください

Spring BootからS3にファイルをアップロードする方法

build.gradle全てを載せているので必要ないものも入っています。

S3に必要な設定にはコメントをつけてます。

buildscript {
	ext {
		kotlinVersion = '1.1.4-3'
		springBootVersion = '1.5.6.RELEASE'
		springCloudVersion = '1.2.1.RELEASE'// 必要
	}
	repositories {
		mavenCentral()
	}
	dependencies {
		classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
		classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
		classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}")
		classpath "io.spring.gradle:dependency-management-plugin:0.5.2.RELEASE"// 必要
	}
}

apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'// 必要

dependencyManagement {
     imports {
          mavenBom 'org.springframework.cloud:spring-cloud-aws:1.2.2.BUILD-SNAPSHOT'// 必要
     }
}

version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
compileKotlin {
	kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
	kotlinOptions.jvmTarget = "1.8"
}

repositories {
	mavenCentral()
	maven { url 'https://repo.spring.io/libs-snapshot' }// 必要
}


dependencies {
	compile('org.springframework.boot:spring-boot-starter-web')
	compile("org.jetbrains.kotlin:kotlin-stdlib-jre8:${kotlinVersion}")
	compile("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
	compile("org.springframework.cloud:spring-cloud-aws-context:${springCloudVersion}")// 必要
}

環境

環境はEclipseとgradleで構築しています。バージョンは下記を参照してください。

  • Kotlin:1.1.4-3
  • Spring Boot:1.5.6.RELEASE
  • Spring Cloud:1.2.1.RELEASE

AWSの認証設定

Spring BootからS3にアクセスできるようにapplication.yamlまたはpropertiesに認証情報とリージョンを設定します。

別の方法として、S3にアクセスできるIAM RoleをEC2に設定することでも可能です。

cloud.aws:
  credentials:
    accessKey: ACCESSKEY
    secretKey: SECRETKEY
  region:
    static: ap-northeast-1
    auto: false

ダウンロード処理

ダウンロードにはAmazonS3ClientのgetObject()メソッドとS3ObjectのgetObjectContent()メソッドを使用します。

ダウンロード処理のサンプルコードは下記です。コード量はすごく少ないのですぐ理解できるかと思います。

package com.sample.aws

import com.amazonaws.services.s3.AmazonS3Client
import com.amazonaws.services.s3.model.CannedAccessControlList
import com.amazonaws.services.s3.model.GetObjectRequest
import com.amazonaws.services.s3.model.ObjectMetadata
import com.amazonaws.services.s3.model.PutObjectRequest
import com.amazonaws.services.s3.model.PutObjectResult
import com.amazonaws.services.s3.model.S3Object
import com.amazonaws.services.s3.model.S3ObjectInputStream
import com.amazonaws.util.IOUtils
import org.springframework.stereotype.Component
import org.springframework.web.multipart.MultipartFile
import java.io.BufferedReader
import java.io.File
import java.io.FileOutputStream
import java.io.InputStream
import java.io.InputStreamReader

@Component
class S3 {

    var amazonS3Client: AmazonS3Client = AmazonS3Client()

    /**
     * S3からファイルをダウンロード
     *
     * @param fileName ダウンロードするファイル名
     * @return ダウンロードしたファイル
     */
    fun download(fileName: String): String {
        val s3Object: S3Object = amazonS3Client.getObject(GetObjectRequest("BUCKET_NAME", fileName));
        val objectData: S3ObjectInputStream = s3Object.getObjectContent()

        var reader: BufferedReader = BufferedReader(InputStreamReader(objectData));
        var content: String = ""
        while (true) {
            var  line: String? = reader.readLine();
            if (line == null) break;
            content += line + "\n"
        }
        objectData.close();
        return content;
    }
}

自分がここでハマったポイントとして、objectDataがInputStreamReaderに渡すとS3ObjectInputStreamじゃなくて、InputStreamを渡してくださいというエラーが出てコンパイルができなかったことでした。

ここが解決できなくてものすごく時間を使ったのですが、com.amazonaws.utiに対してビルドパスが通っていないことが原因ぽかったです。なので、ブルドパスの構成から外部Jarの追加でaws-java-sdk-coreのJarを追加したら解決しました。

たまに、gradleで入れた外部Jarにビルドパスが遠ていないことがあるので謎のコンパイルエラーが出ているときはよく確認するといいかと思います。

ブラウザからダウンロードできるようにする

ブラウザにはJSONを返す時のようなレスポンスではなくダウンロードようにヘッダーをカスタマイズしてあげないといけません。

レスポンスに指定しているクラスも少し特殊なResponseEntityを使用します。設定項目は少ないのでサンプルコードを参考にファイル名を決めてリターンするだけで完了です。

@RequestMapping(value = "/csv/download", method = arrayOf(RequestMethod.GET))
fun downloadItem(): ResponseEntity<ByteArray> {
    var content: String = s3.downloadI("sample.csv")
    var header: HttpHeaders = HttpHeaders()
    header.add("Content-Type", "text/csv;");
    header.setContentDispositionFormData("filename", "sample.csv");
    return ResponseEntity<ByteArray>(content.toByteArray(), header, HttpStatus.OK);
}

関連情報

おすすめ書籍

Springの概要からインストール方法、各コア機能(Security, Sessionなど)の解説が体系的にまとめられています。2018年に出版されたばかりなので情報も新しいです。これからSpring Bootでアプリケーション開発をしたい方の最初に読む一冊としておすすめします。対象は初心者だけでなく上級者まで幅広く学べるので是非読んでみてください!

 

The following two tabs change content below.

髙妻智一

2013年CyberAgent新卒入社 スマホゲームを作る子会社に所属し、サーバーサイドのエンジニアを担当。2年目の終わりから新規子会社の立ち上げに参加し、サーバーサイドのエンジニアリーダーとしてサービースのリリースから運用までを担当。 2018年仮想通貨のスマホウォレットを提供するGinco Incにブロックチェーンエンジニアとして入社。






よく読まれている関連記事はこちら




コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です