file corrupted when downloading using StreamResource

I am creating an excel file using POI, when downloading to the server the file is OK but when I try to have my app prompt the user to download it the user gets prompted and the file downloaded but excel crashes when opening the file.

I call the following method, where ExcelReport is a class that generates the workbook. i use the getBytes() method to use as InputStream

  public void downloadReport(final ReportResult pReportResult, final ReportConfigurationBean pReportConfigurationBean, final Application pApplication) {


        final ExcelReport excelReport = new ExcelReport(pReportResult, pReportConfigurationBean);

         // Set MIME type to binary data to prevent opening of pdf in browser window
         final DynamicStreamResource streamResource =
          new DynamicStreamResource(excelReport.getBytes(), "Report.xls",
          DynamicStreamResource.MIME_TYPE_EXCEL, pApplication);

         streamResource.setCacheTime(5 * 1000); // no cache (<=0) does not work with IE8, (in milliseconds)
         pApplication.getMainWindow().open(streamResource, "_top");
    }

DynamicStreamResource is a class I found
here
on the forums while looking for a solution for my problem

package com.go.portal.util;

import java.io.ByteArrayInputStream;
import java.io.InputStream;

import com.vaadin.Application;
import com.vaadin.terminal.DownloadStream;
import com.vaadin.terminal.StreamResource;

public class DynamicStreamResource extends StreamResource {

 private static final long serialVersionUID = -4304057799149311779L;

 public static final String MIME_TYPE_BINARY_DATA = "application/octet-stream";
 public static final String MIME_TYPE_PDF = "application/pdf";
 public static final String MIME_TYPE_EXCEL = "application/vnd.ms-excel";

 private final byte[] binaryData;
 private final String filename;

 public DynamicStreamResource(final byte[] pBinaryData, final String pFilename,
   final String pMimeType, final Application pApplication) {
  super(new StreamSource() {

  @Override
  public InputStream getStream() {
   return new ByteArrayInputStream(pBinaryData);
  }
  }, pFilename, pApplication);

  this.binaryData = pBinaryData;
  this.filename = pFilename;

  setMIMEType(pMimeType);
 }

 @Override
 public DownloadStream getStream() {
  final DownloadStream downloadStream = super.getStream();

  // Set the "attachment" to force save-dialog. Important for IE7 (and probably IE8)
  downloadStream.setParameter("Content-Disposition", "attachment; filename=\"" + filename + "\"");

  // Enable deterministic progressbar for download
  downloadStream.setParameter("Content-Length", Integer.toString(binaryData.length));

  return downloadStream;
 }

}

At first I thought the problems where on the way I was using POI but after downloading the file to the server, I realized it must be something on the way the bytes are streamed to the user.

Any help would be appreciated.

Never did what you are doing, so there’s no real experience here, but you might try downloading and saving to a file (not just use the Open option, but Save) to see if the size matches. There have been issues in the past with HTTPS connections or the very short cache time you have that may cause the browser to “delete it” before it can be opened. Good luck!

thanks David!

I ended up extending StreamSource directly on the class that creates the report. Implemented the Abstract method getStream as follows:

public InputStream getStream() {
         try {
                /* Write the excel to a buffer. */
                excelBuffer = new ByteArrayOutputStream();
                wb.write(excelBuffer);

                /* Return a stream from the buffer. */
                return new ByteArrayInputStream(
                             excelBuffer.toByteArray());
            } catch (IOException e) {
                 Logger.getLogger(ExcelReport.class.getName()).log(Level.SEVERE, null, e);
                 return null;
            }
    }

Added a button on my Layout to trigger the export:

            exportToExcel.addListener(new Button.ClickListener() {
            public void buttonClick(ClickEvent event) {
                ReportConfigurationBean selectedReport = (ReportConfigurationBean)reportCombo.getValue();
                ReportResult reportResult = null;
                    try {
                        ReportDAO reportDAO = new ReportDAO();
                        reportResult = reportDAO.getReportResult(selectedReport);

                        TPTApplication app = TPTApplication.getCurrentApplication();

                        downloadReport(reportResult, selectedReport, app);

                   

                    } catch (GoException ex) {
                        Logger.getLogger(ReportView.class.getName()).log(Level.SEVERE, null, ex);
                    }
            }

and created the following function to connect the streams:

   public void downloadReport(final ReportResult pReportResult, final ReportConfigurationBean pReportConfigurationBean, final Application pApplication) {


        final ExcelReport excelReport = new ExcelReport(pReportResult, pReportConfigurationBean, null);

        //Save
        StreamResource excelResource =
        new StreamResource(excelReport, pReportConfigurationBean.getReportTitle() + ".xls", pApplication);
        excelResource.setMIMEType("application/vnd.ms-excel"); //mime type excel
        excelResource.setCacheTime(5 * 1000); // no cache (<=0) does not work with IE8, (in milliseconds)
        pApplication.getMainWindow().open(excelResource, "_top");
    }

I am not really sure why the previous implementation was not working. I hope this code helps someone.