12

JavaEEWebアプリケーションを開発しました。このアプリケーションを使用すると、ユーザーはブラウザを使用してファイルをアップロードできます。ユーザーがファイルをアップロードすると、このアプリケーションは最初にアップロードされたファイルをサーバー(サーバーが実行されているサーバー)に保存してから処理します。

現在、次のようにファイルをサーバーに保存しています。

try {
    // formFile represents the uploaded file
    FormFile formFile = programForm.getTheFile();
    String path = getServlet().getServletContext().getRealPath("") + "/"
        + formFile.getFileName();
    System.out.println(path);
    file = new File(path);
    outputStream = new FileOutputStream(file);
    outputStream.write(formFile.getFileData());
}

ここで、formFileはアップロードされたファイルを表します。

問題は、一部のサーバーでは正常に実行されているが、一部のサーバーでgetServlet().getServletContext().getRealPath("")はが返さnullれるため、取得する最終パスがnull/filenameサーバーに保存されないことです。

APIのServletContext.getRealPath()メソッドを確認したところ、次のことがわかりました。

public java.lang.String getRealPath(java.lang.String path)

指定された仮想パスの実際のパスを含む文字列を返します。たとえば、パス"/index.html"はサーバーのファイルシステム上の絶対ファイルパスを返します"http://host/contextPath/index.html"。ここで、contextPathはこのServletContextのコンテキストパスです。

返される実際のパスは、適切なパスセパレータを含め、サーブレットコンテナが実行されているコンピュータとオペレーティングシステムに適した形式になります。サーブレットコンテナが何らかの理由(コンテンツが.warアーカイブから利用可能になっている場合など)で仮想パスを実際のパスに変換できない場合、このメソッドはnullを返します。

nullだから、私がそれらのサーバーにファイルを保存することができる他の方法はありますか?getServlet().getServletContext().getRealPath("")

4

2 に答える 2

21

仕様により、サーブレットコンテナから取得することが保証されている唯一の「実際の」パスは一時ディレクトリです。

あなたはそれを介して得ることができますServletContext.gerAttribute("javax.servlet.context.tempdir")。ただし、これらのファイルはWebコンテキストに表示されません(つまり、これらのファイルを配信するための単純なURLを公開することはできません)。また、ファイルがWebアプリまたはサーバーの再起動後も存続することは保証されません。

作業ファイルを短時間保存する場所が必要な場合は、これで問題ありません。

ディレクトリが本当に必要な場合は、構成パラメータ(環境変数、Javaプロパティ(つまりjava -Dyour.file.here=/tmp/files ...)、web.xmlに設定されたコンテキストパラメータ、Webフォームを介してデータベースに保存された構成パラメータなど)にすることができます。 。)。次に、このディレクトリを設定するのはデプロイヤ次第です。

ただし、後でそのファイルを実際に提供する必要がある場合は、外部ディレクトリをWebアプリに「マウント」するためのコンテナ固有のメカニズムが必要になります(Glassfishは「代替ドキュメントルート」として、他の人は同様の概念を持っています)。 Webアプリの外部でファイルストアを提供するためのサーブレット/フィルターを作成する必要があります。このFileServletは非常に完全であり、ご覧のとおり、独自のFileServletを作成することは難しくはありませんが、正しく行うのは簡単ではありません。

編集:

基本的な要点は同じですが、「getRealPath」を使用するのではなく、単に「getInitParameter」を使用してください。

それで:

String filePath = getServletContext().getInitParameter("storedFilePath") + "/" + fileName;

そして、あなたの道を進んでください。

もう一度編集します。

パスの内容については、絶対パスを指定します。それ以外の場合は、実行中にアプリサーバーがデフォルトパスをどこに設定するかを知る必要があり、各アプリサーバーは異なるディレクトリを使用する可能性があります。たとえば、Glassfishの作業ディレクトリは、実行中のドメインのconfigディレクトリだと思います。特に明白な選択ではありません。

したがって、絶対パスを使用してください。そうすれば、ファイルの行き先がわかり、必要に応じて、そのディレクトリのOSレベルでアクセス許可を制御できます。

于 2010-04-18T17:50:09.483 に答える
13

特に書き込まれたデータを処理する必要がある場合は、JavaEEコンテナからファイルシステムに書き込むことは実際には推奨されません。

  • トランザクションではありません
  • 移植性を損ないます(クラスター環境にいる場合はどうなりますか)
  • ターゲットの場所の外部パラメータを設定する必要があります

これがオプションの場合、ファイルをデータベースに保存するか、JCRリポジトリ(Jackrabbitなど)を使用します。

于 2010-04-18T20:37:56.157 に答える