0

We are developing a Vaadin application, running it on oc4j 10.1.3. There is a window, where the results of a query can be exported as a csv file. After creating the csv file as a vaadin FileResource, opening the file fails. Here is the snippet:

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);

At this point, the resource's uri is: app://APP/1/xy.csv

We have a filter for redirecting the "/" path for "/VAADIN". When this filter gets invoked, the file's uri is /VAADIN/APP/1/xy.csv instead of /APP/1/xy.csv, so i'm removing the unnecessary /VAADIN part, and calling requestdispatcher.forward with the new uri. But here's the fun part, the application still fails, it says in the log:

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.

So the uri is wrong again. It appears in the address bar, and the application resets to the main page. However, with this uri still in the address bar, when i try to create the csv file again, doing either same of some other query in the app, the export part does give back a file, the previously generated one. If i try to do another query again (with the previous url still in the address bar of the browser), it seems to generate the new csv file, but gives back the first file again.

Is it a vaadin bug or some oc4j magic? :)

csaadaam
  • 103
  • 1
  • 3
  • 8

1 Answers1

0

Vaadin framework works on server-side. So why do you need to create unnecessary temp CSV files on server? Try to export desired data directly into the stream.

If you need to export little amounts of data, simply use ByteArrayOutputStream and Vaadin StreamResource. Write your CSV values to OutputStream and give this stream to function such as below:

    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");
    }

As you see, this code does simple conversation from OutputStream to InputStream and uses the result InputStream for Vaadin StreamResource object creation.

'filename' parameter sets up the default name of file which will be loaded into browser on client side (note, that user always can rename files "on fly" using "always display save dialogs" browser option).

Sure, this variant is ugly a bit, because it keeps all exported data in memory.

If you need to export the big amounts of data and don`t want to keep all them in memory, you can use PipedOutputStream or custom circular buffers instead of ByteArrayOutputStream byte buffer. Algorithm will be the same. See article about OutputStream to InputStream conversation and Vaadin book chapter about resources for more information.

P.S. Don`t forget to close input and output streams completely after data exporting succeeds.

daniilyar
  • 1,972
  • 2
  • 18
  • 23
  • Thanks for your suggestion, but it is the same. As the book says in that chapter, `We named the resource as myimage.png. The application adds a resource key to the file name of the resource to make it unique. The full URI will be like http://localhost:8080/testbench/APP/1/myimage.png.` It is the same here, creates a unique URI for the stream as it is a file, the same bad uri and my forward is still useless. And yes, we have to prepare for huge amounts of customer data, so the outputstream-> byte array -> inputstream "conversion" is not acceptable due to memory limitations. – csaadaam Aug 15 '12 at 11:44
  • I'm having the same issue in Chrome but not in Firefox. Have you solved this problem yet? – Monir Apr 12 '13 at 20:48