Java Web アプリケーションでアプリケーション サーバーの外部から静的データを提供する最も簡単な方法 質問する

Java Web アプリケーションでアプリケーション サーバーの外部から静的データを提供する最も簡単な方法 質問する

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に書き込むだけです。OutputStreamHttpServletResponse

レスポンスでは、Content-Typeクライアントが提供したファイルにどのアプリケーションを関連付けるかを知ることができるようにヘッダーを設定する必要があります。また、クライアントがダウンロードの進行状況を計算できるようにヘッダーを設定する必要があります。そうしないと、進行Content-Length状況が不明になります。また、Content-Dispositionattachment名前を付けて保存ダイアログが表示されない場合は、クライアントはそれをインラインで表示しようとします。最後に、ファイルの内容を応答出力ストリームに書き込みます。

このようなサーブレットの基本的な例を次に示します。

@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()

参照:

おすすめ記事