Search code examples
filedownloadresourcesvaadin8

Vaadin 8: extend FiledownLoader


I am trying to extend Vaadin 8 FileDownloader to allow the resource to be generated after the FileDownloader was extended to button. But I am getting this exception: java.lang.RuntimeException: ResourceReference does not support resources of type DynamicFileDownloader

Here is my code:

import com.vaadin.server.DownloadStream;
import com.vaadin.server.FileDownloader;
import com.vaadin.server.Resource;
import com.vaadin.server.StreamResource;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinResponse;
import com.vaadin.server.VaadinSession;
import java.io.IOException;

public class DynamicFileDownloader extends FileDownloader
{

private DynamicDownloadListener dynamicDownloadListener;

public DynamicFileDownloader()
{
  super(new Resource()
  {
     @Override
 public String getMIMEType()
 {
    return "pdf";
 }
  });
}

public void addDynamicDownloadListener(DynamicDownloadListener listener)
{
  dynamicDownloadListener = listener;
}

public void setResource(StreamResource resource)
{
   super.setResource("stream", resource);
}

@Override
public boolean handleConnectorRequest(VaadinRequest request,
 VaadinResponse response, String path) throws IOException
{
  VaadinSession session = getSession();

  session.lock();
  dynamicDownloadListener.beforeDownload();

  DownloadStream stream;

  try
  {
     Resource resource = super.getResource("stream");

     stream = ((StreamResource) resource).getStream();

  } finally
  {
     session.unlock();
  }
   stream.writeResponse(request, response);
   return true;
}

public interface DynamicDownloadListener
{
   public void beforeDownload();
}
 }

How to use:

DynamicFileDownloader dynamicFileDownloader = new DynamicFileDownloader();
 dynamicFileDownloader.addDynamicDownloadListener(() -> {
  try
 {
    // make resource from user input
    dynamicFileDownloader.setResource(resource);
 } catch (ValidationException | IOException e1)
 {

 }
});

dynamicFileDownloader.extend(window.getButtonDownload());

I googled but could not find anything The regular FileDownloader does not allow for dynamic Content from user input, that's why I am trying to extend FileDownloader.


Solution

  • Tatu Lund thank you for your hint. I was able to use the OnDemandFileDownloader. Here is the Code:

    import com.vaadin.server.FileDownloader;
    import com.vaadin.server.StreamResource;
    import com.vaadin.server.VaadinRequest;
    import com.vaadin.server.VaadinResponse;
    
    import java.io.IOException;
    
    public class OnDemandFileDownloader extends FileDownloader
    {
       public interface OnDemandStreamResource extends StreamResource.StreamSource
       {
          String getFilename();
       }
    
       private final OnDemandStreamResource onDemandStreamResource;
    
       public OnDemandFileDownloader(OnDemandStreamResource onDemandStreamResource)
       {
          super(new StreamResource(onDemandStreamResource, ""));
          this.onDemandStreamResource = onDemandStreamResource;
       }
    
       @Override
       public boolean handleConnectorRequest(VaadinRequest request,
         VaadinResponse response, String path) throws IOException
       {
          getResource().setFilename(onDemandStreamResource.getFilename());
          return super.handleConnectorRequest(request, response, path);
       }
    
       private StreamResource getResource()
       {
          return (StreamResource) this.getResource("dl");
       }
    }
    

    And here is how I used it:

    OnDemandFileDownloader.OnDemandStreamResource onDemandStreamResource = new  OnDemandFileDownloader.OnDemandStreamResource()
      {
         @Override
         public String getFilename()
         {
            return  pojo.getName();
         }
    
         @Override
         public InputStream getStream()
         {
            byte[] source = null;
    
           // make source here
            return new ByteArrayInputStream(source);
         }
      };
    
      OnDemandFileDownloader onDemandFileDownloader = new OnDemandFileDownloader(
            onDemandStreamResource);
      onDemandFileDownloader.extend(downloadButton);