Tomcat で Java Web アプリケーションを実行しています。Web UI とアプリケーションによって生成された PDF ファイルの両方に表示される静的画像をロードしたいと考えています。また、Web UI 経由でアップロードすることで、新しい画像が追加され、保存されます。
静的データを Web コンテナー内に保存してこれを実行するのは問題ありませんが、Web コンテナーの外部から静的データを保存および読み込むのは面倒です。
現時点では、静的データを提供するのに Apache のような別の Web サーバーを使用するのは好ましくありません。また、画像をバイナリ形式でデータベースに保存するという考えも好きではありません。
イメージ ディレクトリを Web コンテナー外のディレクトリを指すシンボリック リンクにするなどの提案をいくつか見ましたが、このアプローチは Windows 環境と *nix 環境の両方で機能しますか?
画像の提供を処理するためのフィルターまたはサーブレットを作成することを提案する人もいますが、それらの提案は非常に漠然としており、これを実現する方法に関するより詳細な情報へのポインターがありません。
ベストアンサー1
イメージ ディレクトリを Web コンテナー外のディレクトリを指すシンボリック リンクにするなどの提案をいくつか見ましたが、このアプローチは Windows 環境と *nix 環境の両方で機能しますか?
*nix ファイルシステムのパス規則に従う場合 (つまり、 のようにスラッシュのみを使用する場合/path/to/files
)、醜い文字列連結をいじくり回すことなく、Windows でも動作しますFile.separator
。ただし、このコマンドが呼び出されたのと同じ作業ディスク上でのみスキャンされます。したがって、たとえば Tomcat が にインストールされている場合、C:
は/path/to/files
実際には を指しますC:\path\to\files
。
ファイルがすべて Web アプリの外部にあり、Tomcat でDefaultServlet
それらを処理する必要がある場合、Tomcat で基本的に必要なのは、次の Context 要素をタグ/conf/server.xml
内に追加することだけです。<Host>
<Context docBase="/path/to/files" path="/files" />
この方法では、 からアクセスできるようになりますhttp://example.com/files/...
。JBoss EAP 6.x以前のTomcatベースのサーバーの場合、アプローチは基本的に同じです。ここGlassFish/Payaraの設定例については、ここWildFlyの設定例については、ここ。
ファイルの読み取り/書き込みを自分で制御したい場合は、Servlet
これ用の を作成する必要があります。これは基本的に、InputStream
たとえば のフレーバーのファイルの を取得し、それを のFileInputStream
に書き込むだけです。OutputStream
HttpServletResponse
レスポンスでは、Content-Type
クライアントが提供したファイルにどのアプリケーションを関連付けるかを知ることができるようにヘッダーを設定する必要があります。また、クライアントがダウンロードの進行状況を計算できるようにヘッダーを設定する必要があります。そうしないと、進行Content-Length
状況が不明になります。また、Content-Disposition
attachment
名前を付けて保存ダイアログが表示されない場合は、クライアントはそれをインラインで表示しようとします。最後に、ファイルの内容を応答出力ストリームに書き込みます。
このようなサーブレットの基本的な例を次に示します。
@WebServlet("/files/*")
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String filename = URLDecoder.decode(request.getPathInfo().substring(1), "UTF-8");
File file = new File("/path/to/files", filename);
response.setHeader("Content-Type", getServletContext().getMimeType(filename));
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");
Files.copy(file.toPath(), response.getOutputStream());
}
}
url-pattern
たとえば のにマップされている場合/files/*
、 で呼び出すことができますhttp://example.com/files/image.png
。この方法では、 よりもリクエストをより細かく制御できますDefaultServlet
。たとえば、デフォルトの画像 (つまりif (!file.exists()) file = new File("/path/to/files", "404.gif")
など) を提供することができます。また、 の使用はSEO フレンドリーであるため、request.getPathInfo()
上記では が推奨されています。request.getParameter()
そうしないと、IE は の実行中に正しいファイル名を選択しません。名前を付けて保存。
データベースからファイルを提供するのに同じロジックを再利用できます。new FileInputStream()
を に置き換えるだけですResultSet#getInputStream()
。