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"))
);
こんな風に、画像や他のアセットのアクセスを制限することもできます。