2012-08-13 137 views
0

我们正在开发Vaadin应用程序,在oc4j 10.1.3上运行它。有一个窗口,可以将查询结果导出为csv文件。在创建csv文件作为vaadin FileResource后,打开文件失败。 下面是摘录:Vaadin请求的资源未找到

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错误还是一些oc4j魔法? :)

回答

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和用来Vaadin StreamResource对象的创建结果的InputStream。

'filename'参数设置文件的默认名称,该文件将被加载到客户端的浏览器中(注意,用户总是可以使用“始终显示保存对话框”浏览器选项来“随时”重命名文件)。

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

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

P.S.数据导出成功后,请勿忘记关闭输入和输出流。

+0

感谢您的建议,但它是一样的。正如该书在该章中所说,“我们将资源命名为myimage.png。应用程序将资源键添加到资源的文件名以使其唯一。完整的URI将像http:// localhost:8080/testbench/APP/1/myimage.png.'这里是一样的,为流创建一个唯一的URI,因为它是一个文件,同样不好的URI和我的前进依然无用。是的,我们必须准备大量的客户数据,所以由于内存限制,输出流 - >字节数组 - >输入流“转换”是不可接受的。 – csaadaam 2012-08-15 11:44:28

+0

我在Chrome中遇到同样的问题,但在Firefox中没有问题。你有没有解决这个问题呢? – Monir 2013-04-12 20:48:02