0

oc4j 10.1.3 で実行する Vaadin アプリケーションを開発しています。クエリの結果を csv ファイルとしてエクスポートできるウィンドウがあります。csv ファイルを vaadin FileResource として作成した後、ファイルを開くことができません。スニペットは次のとおりです。

File file = exporter.exportToFile();
final FileResource resource = new FileResource(file, getApplication());
resource.setCacheTime(0);
resource.getStream().setParameter("Content-Disposition", "attachment;filename=\""+file.getName()+"\"");
event.getButton().getWindow().open(resource);

この時点で、リソースの uri は次のようになります。app://APP/1/xy.csv

「/VAADIN」の「/」パスをリダイレクトするフィルタがあります。このフィルターが呼び出されると、ファイルの uri が/VAADIN/APP/1/xy.csvではなく に/APP/1/xy.csvなるため、不要な /VAADIN 部分を削除requestdispatcher.forwardし、新しい uri で呼び出します。しかし、ここに楽しい部分があります。アプリケーションはまだ失敗します。ログには次のように書かれています。

Aug 13, 2012 1:55:58 PM com.vaadin.terminal.gwt.server.AbstractApplicationServlet serveStaticResourcesInVAADIN
INFO: Requested resource [VAADIN/APP/1/xy.csv] not found from filesystem or through class loader. Add widgetset and/or theme JAR to your classpath or add files to WebContent/VAADIN folder.

だから、ウリはまた間違っています。アドレス バーに表示され、アプリケーションはメイン ページにリセットされます。ただし、この uri がまだアドレス バーにある状態で、csv ファイルを再度作成しようとすると、アプリで他のクエリと同じことを行うと、エクスポート部分は以前に生成されたファイルを返します。別のクエリを再度実行しようとすると (以前の URL がブラウザのアドレス バーに残っている)、新しい csv ファイルが生成されたように見えますが、最初のファイルが返されます。

それは vaadin のバグですか、それとも oc4j マジックですか? :)

4

1 に答える 1

0

Vaadin フレームワークはサーバー側で動作します。では、なぜサーバー上に不要な一時 CSV ファイルを作成する必要があるのでしょうか? 必要なデータをストリームに直接エクスポートしてみてください。

少量のデータをエクスポートする必要がある場合は、単純に ByteArrayOutputStream と Vaadin StreamResource を使用してください。CSV 値を OutputStream に書き込み、このストリームを以下のような関数に渡します。

    public void openResourceFromStream(final OutputStream out, String filename) {
    StreamSource streamSource = new StreamSource() {
        private static final long serialVersionUID = 1L;

        @Override
        public InputStream getStream() {
            ByteArrayOutputStream byteStream = (ByteArrayOutputStream) out;
            return new ByteArrayInputStream(byteStream.toByteArray());
        }
    };

    Resource sr = new StreamResource(streamSource, filename, getApplication());
    getWindow().open(sr, "_parent");
    }

ご覧のとおり、このコードは OutputStream から InputStream への単純な会話を行い、結果の InputStream を使用して Vaadin StreamResource オブジェクトを作成します。

「filename」パラメーターは、クライアント側のブラウザーにロードされるファイルのデフォルト名を設定します (ユーザーは、「常に保存ダイアログを表示する」ブラウザー オプションを使用して、「その場で」いつでもファイルの名前を変更できることに注意してください)。

確かに、このバリアントは、エクスポートされたすべてのデータをメモリに保持するため、少し醜いです。

大量のデータをエクスポートする必要があり、すべてをメモリに保持したくない場合は、ByteArrayOutputStream バイト バッファーの代わりに、PipedOutputStream またはカスタム循環バッファーを使用できます。アルゴリズムは同じになります。詳細については、OutputStream から InputStream への会話に関する記事、リソースに関する Vaadin の本の章を参照してください。

PS データのエクスポートが成功した後、入力ストリームと出力ストリームを完全に閉じることを忘れないでください。

于 2012-08-14T23:12:20.827 に答える