找不到Vaadin请求的资源

时间:2012-08-13 15:02:11

标签: java vaadin oc4j

我们正在开发一个Vaadin应用程序,在oc4j 10.1.3上运行它。有一个窗口,可以将查询结果导出为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部分,并使用新的uri调用requestdispatcher.forward。 但这是有趣的部分,应用程序仍然失败,它在日志中说:

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又错了。它出现在地址栏中,应用程序将重置为主页面。但是,由于此uri仍在地址栏中,当我尝试再次创建csv文件时,在应用程序中执行相同的其他查询时,导出部分会返回一个文件,即先前生成的文件。如果我再次尝试再次执行另一个查询(前一个URL仍然在浏览器的地址栏中),它似乎会生成新的csv文件,但会再次返回第一个文件。

是vaadin bug还是某些oc4j魔法? :)

1 个答案:

答案 0 :(得分: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'参数设置将在客户端加载到浏览器中的文件的默认名称(注意,该用户始终可以使用“始终显示保存对话框”浏览器选项“在运行中”重命名文件)。

当然,这个变体有点难看,因为它将所有导出的数据保存在内存中。

如果您需要导出大量数据并且不想将所有数据保存在内存中,则可以使用PipedOutputStream或自定义循环缓冲区而不是ByteArrayOutputStream字节缓冲区。 算法将是相同的。见article about OutputStream to InputStream conversationVaadin book chapter about resources了解更多信息。

P.S。在数据导出成功后,不要忘记完全关闭输入和输出流。