Play Frameworkが非常に便利ですので、Apiサーバーとして使ってます。この度、自分のサーバーに持ってる画像などなアセットをそのまま返したい場合(例え、アンギュラーのフロントで表示したいなど)にどうすればいいかを説明します。 それぞれの状況に合わせて、二つの方法を説明します。
とりあえず、…image.jpgに画像を出したい!
つまり、誰でもそのurlにいくとその画像がみれるような場合です。 この方法は割と簡単です。
conf/routesのファイルに
GET /assets/*file controllers.Assets.versioned(path="/public/images/", file)
これで、/public/images/
のディレクトリーをベースにして、「ファイル」というパス変数に当てはまるファイルをそのまま出せます。
www.example.com/assets/cats/myCat.png
は /public/images/cats/myCat.png
にあるファイルを出します。(なかったら、404エラーが出ます)
ちなみに、Idea使ってる方々はこのようなdeprecatedという知らせを見ることもあると思いますが、Ideaのバグらしいです。(link: https://github.com/playframework/playframework/issues/7521)
このように、Angularのクライアントで、<img src="www.example.com/assets/cats/myCat.png" />
このイメージのアクセスを制限したいですが…
アクセス制限、何かのトラッキング・編集などのことがやりたい場合もあると思います。その場合は直接routesから返したらできなくなるかと思いますが、別な方法もあります!
では、routesにこう追加しましょう
GET /getImage controllers.HomeController.getImage
getImageの中でバリデーションやアナリティクスなど、でもできます。 欲しいイメージや、アクセス権限の情報がGET変数で送られてるとしますと、FormFactoryとDynamicForm を使って、コントローラーからその変数のアクセスができます。
public class MyController extends Controller { @Inject private FormFactory formFactory; public Result getImage() { ... } }
まずは、FormFactoryをInjectionで使えるようになる。そして、getImageの書き方は...
DynamicForm dynamicForm = formFactory.form.bindFromRequest(); // 適切なログインチェックを行う if(!isLoggedIn(dynamicForm)) { // もしユーザーがログインしてない場合には、対応する。 return ....; //アクセス制限する。 }
まずは、バリデーションができる、そしてアクセス制限したい場合にはふさわしい風に行える。 その後、ユーザーが頼んでるイメージの正式なパスを作成し、Resultを返す。
// ユーザーが送ってるファイル名的なパスと実際のサーバーのパスが違うのはず。 String path = getRealImagePath(dynamicForm.get("")); java.nio.file.Path deliveryPath = Paths.get(path); // これはPlayFrameworkに存在する、ファイルをだす方法: return new Result( new ResponseHeader(200, Collections.emptyMap()), new HttpEntity.Streamed(FileIO.fromPath(deliveryPath), Optional.empty(), Optional.of("image/png")) );
こんな風に、画像や他のアセットのアクセスを制限することもできます。