Skip Navigation
Show nav
Heroku Dev Center
  • Get Started
  • ドキュメント
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
  • ドキュメント
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log inorSign up
View categories

Categories

  • Heroku のアーキテクチャ
    • Dyno (アプリコンテナ)
    • スタック (オペレーティングシステムイメージ)
    • ネットワーキングと DNS
    • プラットフォームポリシー
    • プラットフォームの原則
  • コマンドライン
  • デプロイ
    • Git を使用したデプロイ
    • Docker によるデプロイ
    • デプロイ統合
  • 継続的デリバリー
    • 継続的統合
  • 言語サポート
    • Node.js
    • Ruby
      • Bundler の使用
      • Rails のサポート
    • Python
      • Python でのバックグランドジョブ
      • Django の使用
    • Java
      • Maven の使用
      • Java でのデータベース操作
      • Play Framework の使用
      • Spring Boot の使用
      • Java の高度なトピック
    • PHP
    • Go
      • Go の依存関係管理
    • Scala
    • Clojure
  • データベースとデータ管理
    • Heroku Postgres
      • Postgres の基礎
      • Postgres Getting Started
      • Postgres のパフォーマンス
      • Postgres のデータ転送と保持
      • Postgres の可用性
      • Postgres の特別なトピック
    • Heroku Redis
    • Apache Kafka on Heroku
    • その他のデータストア
  • モニタリングとメトリクス
    • ログ記録
  • アプリのパフォーマンス
  • アドオン
    • すべてのアドオン
  • 共同作業
  • セキュリティ
    • アプリのセキュリティ
    • ID と認証
    • コンプライアンス
  • Heroku Enterprise
    • Private Space
      • インフラストラクチャネットワーキング
    • Enterprise Accounts
    • Enterprise Team
    • Heroku Connect (Salesforce 同期)
      • Heroku Connect の管理
      • Heroku Connect のリファレンス
      • Heroku Connect のトラブルシューティング
    • シングルサインオン (SSO)
  • パターンとベストプラクティス
  • Heroku の拡張
    • Platform API
    • アプリの Webhook
    • Heroku Labs
    • アドオンのビルド
      • アドオン開発のタスク
      • アドオン API
      • アドオンのガイドラインと要件
    • CLI プラグインのビルド
    • 開発ビルドパック
    • Dev Center
  • アカウントと請求
  • トラブルシューティングとサポート
  • Integrating with Salesforce
  • 言語サポート
  • Java
  • Play Framework の使用
  • Java および Play 2 を使用したファイルアップロードのための Amazon S3 の使用

Java および Play 2 を使用したファイルアップロードのための Amazon S3 の使用

日本語 — Switch to English

最終更新日 2022年11月14日(月)

Table of Contents

  • AWS ライブラリ
  • Play 2 用の S3 プラグイン
  • S3Plugin の設定
  • S3File モデル
  • データベースの設定
  • アプリケーションのコントローラー
  • インデックスビュー
  • ルート
  • Heroku 上での実行
  • より深い学習

AWS S3​ などのストレージサービスを使用してファイルアップロードを保存すると、単なるローカルファイルシステムへのファイルの保存と比較して 大幅なスケーラビリティ、信頼性、および速度の向上が得られます。S3 または同様のストレージサービスは、スケーリングに対応したアプリケーションを設計する場合に重要であり、Heroku の一時的なファイルシステム​を完全に補完するものです。

この記事では、Play 2 を使用して Amazon S3 にファイルアップロードを保存する Java Web アプリケーションを作成する方法について説明します。 この記事を読む前に、必要な S3 の資格情報やキーを確立する方法を示すと共に、このようなアプローチのメリットを詳細に説明している「AWS S3 を使用して静的アセットとファイルアップロードを格納する​」を確認してください。

この記事のサンプルアプリケーションのソースは、GitHub​ で入手できます。

Heroku で Play 2 を初めて使用する場合は、Play 2 のドキュメントの「Deploying to Heroku​」(Heroku へのデプロイ) を参照する必要があります。

AWS ライブラリ

S3 では、このサービスと対話するための RESTful API が提供されます。 その API をラップする Java ライブラリが存在するため、Java コードからの対話が簡単になっています。 Play 2 プロジェクトで、project/Build.scala​ の appDependencies​ セクションを更新することによって、アプリケーションへの aws-java-sdk​ の依存関係を追加できます。

val appDependencies = Seq(
  "com.amazonaws" % "aws-java-sdk" % "1.3.11"
)

Play 2 プロジェクトで依存関係を更新したら、Play 2 サーバーを再起動し、すべての IDE 設定ファイル (Eclipse および IntelliJ) を再生成する必要があります。

Play 2 用の S3 プラグイン

Play 2 には、サーバーの起動時に自動的に起動できるプラグインを作成する方法が用意されています。 Play 2 用の正式な S3 プラグインはまだ存在しませんが、次の内容を含む app/plugins/S3Plugin.java​ という名前のファイルを作成することによって独自のプラグインを作成できます。

package plugins;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import play.Application;
import play.Logger;
import play.Plugin;

public class S3Plugin extends Plugin {

    public static final String AWS_S3_BUCKET = "aws.s3.bucket";
    public static final String AWS_ACCESS_KEY = "aws.access.key";
    public static final String AWS_SECRET_KEY = "aws.secret.key";
    private final Application application;

    public static AmazonS3 amazonS3;

    public static String s3Bucket;

    public S3Plugin(Application application) {
        this.application = application;
    }

    @Override
    public void onStart() {
        String accessKey = application.configuration().getString(AWS_ACCESS_KEY);
        String secretKey = application.configuration().getString(AWS_SECRET_KEY);
        s3Bucket = application.configuration().getString(AWS_S3_BUCKET);

        if ((accessKey != null) && (secretKey != null)) {
            AWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey);
            amazonS3 = new AmazonS3Client(awsCredentials);
            amazonS3.createBucket(s3Bucket);
            Logger.info("Using S3 Bucket: " + s3Bucket);
        }
    }

    @Override
    public boolean enabled() {
        return (application.configuration().keys().contains(AWS_ACCESS_KEY) &&
                application.configuration().keys().contains(AWS_SECRET_KEY) &&
                application.configuration().keys().contains(AWS_S3_BUCKET));
    }

}

S3Plugin​ は 3 つの設定パラメータを読み取り、S3 への接続を設定して、ファイルを保持するための S3 バケットを作成します。 このプラグインを有効にするには、次の内容を含む conf/play.plugins​ という名前の新しいファイルを作成します。

1500:plugins.S3Plugin

これは、S3Plugin​ に 1500​ の優先度で開始するよう指示します。つまり、すべてのデフォルトの Play プラグインの後に起動します。

S3Plugin の設定

S3Plugin​ が機能するには、3 つの設定パラメータ​が必要です。 aws.access.key​ は AWS アクセスキーを保持し、aws.secret.key​ は AWS 秘密鍵を保持します。 また、aws.s3.bucket​ パラメータを使用してグローバル固有バケット ID を指定することも必要です。 これらの設定パラメータを設定するには、それを conf/application.conf​ ファイルに追加します。

aws.access.key=${?AWS_ACCESS_KEY}
aws.secret.key=${?AWS_SECRET_KEY}
aws.s3.bucket=com.something.unique

機密の接続情報を設定ファイルに直接入力することはお勧めしません​。代わりに aws.access.key​ と aws.secret.key​ は AWS_ACCESS_KEY​ と AWS_SECRET_KEY​ という名前の環境変数から取得します。 これらの値は、次のようにローカルにエクスポートすることによって設定できます。

$ export AWS_ACCESS_KEY=<Your AWS Access Key>
$ export AWS_SECRET_KEY=<Your AWS Secret Key>

aws.s3.bucket​ の名前は、アプリケーションに関連した一意の名前に変更する必要があります。たとえば、デモアプリケーションでは値 com.heroku.devcenter-java-play-s3​ を使用していますが、デモを自分で実行する場合は、これを他の名前に変更する必要があります。

S3File モデル

単純な S3File​ モデルオブジェクトはファイルを S3 にアップロードし、ファイルメタデータをデータベースに保存します。 次の内容を含む app/models/S3File.java​ という名前のファイル内に新しい S3File​ モデルを作成できます。

package models;

import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.PutObjectRequest;
import play.Logger;
import play.db.ebean.Model;
import plugins.S3Plugin;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Transient;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.UUID;

@Entity
public class S3File extends Model {

    @Id
    public UUID id;

    private String bucket;

    public String name;

    @Transient
    public File file;

    public URL getUrl() throws MalformedURLException {
        return new URL("https://s3.amazonaws.com/" + bucket + "/" + getActualFileName());
    }

    private String getActualFileName() {
        return id + "/" + name;
    }

    @Override
    public void save() {
        if (S3Plugin.amazonS3 == null) {
            Logger.error("Could not save because amazonS3 was null");
            throw new RuntimeException("Could not save");
        }
        else {
            this.bucket = S3Plugin.s3Bucket;

            super.save(); // assigns an id

            PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, getActualFileName(), file);
            putObjectRequest.withCannedAcl(CannedAccessControlList.PublicRead); // public for all
            S3Plugin.amazonS3.putObject(putObjectRequest); // upload file
        }
    }

    @Override
    public void delete() {
        if (S3Plugin.amazonS3 == null) {
            Logger.error("Could not delete because amazonS3 was null");
            throw new RuntimeException("Could not delete");
        }
        else {
            S3Plugin.amazonS3.deleteObject(bucket, getActualFileName());
            super.delete();
        }
    }

}

S3File​ クラスには、プライマリキーである id​、ファイルが保存される bucket​、ファイルの name​、実際にはデータベースに保存されない実際の file​ (そのため、これは @Transient​) という 4 つのパラメータがあります。

S3File​ クラスは save​ メソッドを上書きします。ここでは、設定されたバケット名を S3Plugin​ から取得してから S3File​ をデータベースに保存し、そこで新しい id​ が割り当てられます。 その後、このファイルは S3 Java ライブラリを使用して S3 にアップロードされます。

この例では、ファイルのアクセス許可か public に設定されている (リンクによりすべてのユーザーに表示される) ことに注意してください。

逆に、S3File​ クラスは、S3File​ がデータベースから削除される前に S3 上のファイルが削除されるように delete​ メソッドも上書きします。

S3 上の実際のファイル名は getActualFileName​ メソッドから派生しています。これは、id​ と元のファイル名が /​ で連結されたものです。 S3 にはディレクトリの概念はありませんが、これはシミュレートし、ファイル名の衝突を回避しています。

S3File​ クラスにはまた、S3 の HTTP サービスを使用してファイルへの URL を返す getUrl​ メソッドもあります。 これは、ユーザーが S3 からファイルを取得するための最も直接的な方法ですが、これが機能するのは単に、ファイルが public のアクセス権を持つように設定されているためです。

別の方法として、ファイルを private にし、S3 の API 呼び出しを使用してファイルをフェッチする別のメソッドを S3File​ に用意することもできます。

データベースの設定

ここではデータベースを使用しているため、conf/application.conf​ で EBean とデータベース接続を設定する必要があります。

db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:mem:play"
ebean.default="models.*"

これらの値はローカルでの開発には有効ですが、Heroku 上で実行する場合は、新しい Play アプリに対して自動的にプロビジョニングされる Heroku Postgres アドオン​を使用できます。 プロジェクトに PostgreSQL JDBC ドライバーを追加するには、project/Build.scala​ ファイルに次の依存関係を追加します。

"org.postgresql" % "postgresql" % "9.4-1201-jdbc4"

Play に PostgreSQL データベースを使用するよう指示するには、次の内容を含む Procfile​ という名前のファイルを作成します。

web: target/start -Dhttp.port=$PORT -DapplyEvolutions.default=true -Ddb.default.driver=org.postgresql.Driver -Ddb.default.url=$DATABASE_URL

これにより、Heroku 上でアプリケーションが実行されると、データベース設定が (PostgreSQL を使用するように) 上書きされます。

アプリケーションのコントローラー

これで、ファイルメタデータを保持し、S3 にファイルをアップロードするモデルが用意されたので、アップロード Web ページのレンダリングや実際のファイルアップロードを処理するコントローラーを作成しましょう。 次の内容を含む app/controllers/Application.java​ という名前のファイルを作成 (または更新) します。

package controllers;

import models.S3File;
import play.db.ebean.Model;
import play.mvc.Controller;
import play.mvc.Result;
import play.mvc.Http;

import views.html.index;

import java.util.List;
import java.util.UUID;

public class Application extends Controller {

    public static Result index() {
        List<S3File> uploads = new Model.Finder(UUID.class, S3File.class).all();
        return ok(index.render(uploads));
    }

    public static Result upload() {
        Http.MultipartFormData body = request().body().asMultipartFormData();
        Http.MultipartFormData.FilePart uploadFilePart = body.getFile("upload");
        if (uploadFilePart != null) {
            S3File s3File = new S3File();
            s3File.name = uploadFilePart.getFilename();
            s3File.file = uploadFilePart.getFile();
            s3File.save();
            return redirect(routes.Application.index());
        }
        else {
            return badRequest("File upload error");
        }
    }

}

Application​ クラスの index​ メソッドは、データベースに S3File​ オブジェクトに関するクエリを実行した後、それをレンダリングのために index​ ビューに渡します。 upload​ メソッドはファイルアップロードを受信し、それで新しい S3File​ を作成し、そのアップロードを保存してから元のインデックスページにリダイレクトします。

インデックスビュー

ここで、ユーザーがファイルをアップロードするために使用できるフォームを含み、アップロードの一覧表示も行う単純なインデックスページを作成しましょう。 次の内容を含む app/views/index.scala.html​ という名前のファイルを作成 (または更新) します。

@(s3Files: List[models.S3File])
 < !DOCTYPE html>

<html>
<head>
    <title>File Upload with Java, Play 2, and S3</title>
    <link rel="shortcut icon" type="image/png" href="@routes.Assets.at("images/favicon.png")">
</head>
<body>
    <h1>Upload a file:</h1>
    @helper.form(action = routes.Application.upload, 'enctype -> "multipart/form-data") {
        <input type="file" name="upload">
        <input type="submit">
    }

    <h1>Uploads:</h1>
    <ul>
    @for(upload <- uploads) {
        <li><a href="@upload.getUrl()">@upload.name</a></li>
    }
    </ul>

</body>
</html>

このビューには、ファイルアップロードのフォーム (helper.form​ メソッドを使用して作成) とファイルの一覧が含まれています。

ルート

設定する必要のある最後のものがルートです。 conf/routes​ ファイルには、HTTP リクエストの動詞とパスのコントローラーメソッドへのマッピングが含まれています。 GET リクエストを Application.index​ メソッドに、POST リクエストを Application.upload​ メソッドにマッピングするには、conf/routes​ ファイルに次の行​を追加します。

GET     /                           controllers.Application.index()
POST    /                           controllers.Application.upload()

これで、このアプリケーションはローカルで完全に動作します。

Heroku 上での実行

サンプルプロジェクトの Git リポジトリ​からソースを複製しなかった場合は、ファイルを新しい Git リポジトリに追加してコミットする必要があります。

$ git init
$ git add .
$ git commit -m init

これで、Heroku で新しいアプリケーションをプロビジョニングできます。

$ heroku create

アプリケーションの環境設定として AWS 接続キーを設定します。

$ heroku config:set AWS_ACCESS_KEY=<Your AWS Access Key> AWS_SECRET_KEY=<Your AWS Secret Key>

Heroku でアプリケーションをデプロイするには、Git リポジトリを Heroku にプッシュします。

$ git push heroku master

次に、アプリケーションが動作していることを確認します。

$ heroku open

より深い学習

これは非常に単純な例にすぎないため、本番ユースケースで改善できる可能性のあるいくつかの領域が存在します。 この例では、ファイルのダウンロードは Amazon S3 から処理されました。 より優れた設定は、Amazon CloudFront​ を使用したアップロードのエッジキャッシュです。

この例では、ファイルはまず Play アプリに移動した後 S3 に移動するため、2 ホップのアップロードを実行しています。 S3 に直接 POST を送信する​ことによって、最初のホップをスキップして S3 に直接アップロードできます。

最後に、アップロード (やすべての IO) はブロック操作であるため、より多くの並列リクエストを処理できるように Play サーバーのスレッドプールサイズを増やす​ (デフォルトは、わずか 4) ことが必要になる可能性があります。

関連カテゴリー

  • Play Framework の使用
Java および Play Framework での Heroku の WebSocket の使用 Java および Play Framework での Heroku の WebSocket の使用

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Podcasts
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing

Subscribe to our monthly newsletter

Your email address:

  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Heroku Podcasts
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Facebook
  • Instagram
  • Github
  • LinkedIn
  • YouTube
Heroku is acompany

 © Salesforce.com

  • heroku.com
  • Terms of Service
  • Privacy
  • Cookies
  • Cookie Preferences