1

私はウェブアプリ(携帯電話用)を開発しています。画像を表示したい xhtml ページが 1 つあります。このページはハード ドライブにローカルに保存されています (例: D:\pictures\test.jpg)。画像がローカルのハードドライブにある場合、ブラウザーは画像をブロックするため、ユーザーが xhtml ページに入ると、localHD に保存されている画像が webApp ディレクトリにコピーされるメソッドを javabean に記述しました。ユーザーがページを離れた後、webapp 内のコピーされたファイルを削除する必要があります。そのため、アプリを実行しているとき、コピーは完全に機能し、写真は正しく表示されます。ただし、ファイルを削除する必要がある場合、次のエラー メッセージが表示されます。

java.nio.file.FileSystemException: D:\WebAppPath\src\main\webapp\resources\pics\test.jpg: ファイルが別のプロセスによって使用されているため、プロセスにアクセスできません。

奇妙なことに、アプリケーションを停止して再起動した後、同じイメージがまだ webApp ディレクトリにある場合は削除できます。(ただし、一度だけ。再コピーした後、エラーメッセージが再び表示されます。)

また、Windows エクスプローラーを使用して手動でファイルを削除しようとすると、Java(TM) Platform SE Binary で使用されているため、ファイルを削除できないというエラー メッセージが表示されます。

したがって、ファイルを (手動または Bean 経由で) 削除するには、アプリケーションの再起動を待つ必要がありますが、これはもちろんエンド ユーザーにとって受け入れられる解決策ではありません。

Primefaces および Primefaces Mobile コンポーネントで JSF2.0 を使用しています。私の IDE は Netbeans で、Spring Webflow フレームワークを使用して、xhtml ページ間でアクション/メソッドをナビゲートおよびトリガーします。

JavaBean のコピー メソッドのコードは次のとおりです。

    public void copyFotoToLocalhost() {
    if (fotoList.size() > 0) {
        for (int i = 0; i < fotoList.size(); i++) {
            Foto tempPic = fotoList.get(i);
            String tempItemName = tempPic.getItemName();
            String originalFile = "D:\\localFilepath\\" + tempItemName;
            String tempFileName = "D:\\WebAppPath\\src\\main\\webapp\\resources\\pics\\" + tempItemName;
            File existTest = new File(tempFileName);

            if (existTest.exists() == false) {
                try {
                    File orFile = new File(originalFile);
                    File tempFile = new File(tempFileName);


                    InputStream in = new FileInputStream(orFile);
                    OutputStream out = new FileOutputStream(tempFile);

                    byte[] buf = new byte[8192];
                    int len;
                    while ((len = in.read(buf)) > 0) {
                        out.write(buf, 0, len);
                    }
                    in.close();
                    out.close();

                    tempFile.setWritable(true);

                    System.out.println("File copied.");
                } catch (FileNotFoundException ex) {
                    System.out.println(ex.getMessage() + " in the specified directory.");
                    System.exit(0);
                } catch (IOException e) {
                    System.out.println(e.getMessage());
                }
            }
        }
    }
}

delete メソッドのコードは次のとおりです。

public void deleteFotos() {
        if (fotoList.size() > 0) {
            for (int i = 0; i < fotoList.size(); i++) {
                Foto tempPic = fotoList.get(i);
                String tempItemName = tempPic.getItemName();

                Path tempLocation = Paths.get("D:\\webAppPath\\src\\main\\webapp\\resources\\pics\\" + tempItemName);
                fotoList.remove(i);
                i--;
                try {
                    Files.deleteIfExists(tempLocation);
                    System.out.println("sucessfully deleted" + tempPic.getItemName());
                } catch (IOException ex) {
                    Logger.getLogger(WundDokuBean.class.getName()).log(Level.SEVERE, null, ex);
                    System.out.println("Fail @ " + tempPic.getItemName());
                }

            }
            fotoList.clear();
        }

これを修正する方法はありますか?

私の問題を理解していただければ幸いです。そうでない場合は、必要な情報を教えてください。提供できるように努めます。

4

1 に答える 1

1

画像を表示したい xhtml ページが 1 つあります。このページはハード ドライブにローカルに保存されています (例: D:\pictures\test.jpg)。画像がローカルのハードドライブにある場合、ブラウザーは画像をブロックするため (...)

最初に概念上の誤解を解消したいと思います。ブラウザがブロックしていない場合は正常に機能することを期待しているようです。これは完全に真実ではありません。HTML 出力で画像がインライン化されることを期待しているようです。いいえ、HTML ページから個別に独立してダウンロードされます。ローカル ディスク ファイル システム パスを使用し続けた場合、Web ページの訪問者がディスク ファイル システムのまったく同じ場所にまったく同じファイルを持っている場合のみ機能ます。実際には、これは明らかにそうではありません。Web ブラウザーと Web サーバーの両方が物理的に同じマシンで実行されている場合にのみ機能します。


ファイルを削除できないという具体的な問題に戻ると、それは通常、サーブレットコンテナが展開された WAR フォルダー内のファイルをロックするために発生します。正確な理由はわかりませんが、このアプローチ全体がとにかく間違っているため、ここでは関係ありません。展開された WAR ファイルがディスク ファイル システムではなく、サーバーのメモリに展開されている場合、このアプローチは失敗します。また、環境固有のディスク ファイル システム パスをハードコーディングすることもお勧めできません。環境を変更するたびに、WAR全体を編集、書き直し、再コンパイル、再構築する必要があります。つまり、webapp は移植可能ではありません。

ファイルを元の場所に保管し、実際の URL で公開する必要があります。これは、次の 2 つの一般的な方法で実現できます。

  1. を指す仮想ホストをサーバー構成に追加しますD:\localFilepath\。それを達成する方法は、使用するサーバーによって異なります。使用されているサーバーのメーカー/バージョンについては何も言われませんでしたが、Spring を使用すると、完全な Java EE スタックを使用できず、Tomcat などのベアボーン JSP/サーブレット コンテナーを使用している可能性が高いことが示唆されます。その場合、次の行をそのに追加するだけ/conf/server.xmlです:

    <Context docBase="D:\localFilepath" path="/fotos" />
    

    このようにして、 から入手できますhttp://localhost:8080/fotos/*


  2. D:\localFilepathHTTP レスポンスからファイルを読み書きするサーブレットを作成します。Servlet 3.0 と Java 7 を使えば、とても簡単です。キックオフの例を次に示します (nullchecks/file-exist-checks/ doHead()/caching/resuming は簡潔にするために省略されています)。

    @WebServlet("/fotos/*")
    public class FotosServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletExcpetion, IOException {
            File file = new File("D:/localFilepath", request.getPathInfo().substring(1));
            response.setHeader("Content-Type", getServletContext().getMimeType(file.getName()));
            response.setHeader("Content-Length", String.valueOf(file.length()));
            Files.copy(file.toPath(), response.getOutputStream());
        }
    
    }
    

    基本的にはそれだけです。このようにして、 で利用できますhttp://localhost:8080/contextname/fotos/*

于 2013-08-23T12:06:20.130 に答える