Search code examples
javavaadin8

vaadin FileDownloader reset extension


As we know, we have to extend FileDownloader with button to be able to download file.

//
Button downloadButton = new Button("download");

private void  updateFileForDownload(){
    ...       
    StreamResource sr = getFileStream();
    FileDownloader fileDownloader = new FileDownloader(sr);
    fileDownloader.extend(downloadButton);
    ...
}
private StreamResource getFileStream() {
    StreamResource.StreamSource source = () -> new ByteArrayInputStream(binderDocument.getBean().getFile());
    StreamResource resource = new StreamResource(source, binderDocument.getBean().getFilename());
    return resource;
}

I have some problem in my application. If i call method updateFileForDownload more than one time a get more than one file by clicking on downloadButton. I need reset extension for Button or for FileDownloader. I tried both:

 downloadButton.removeExtension(fileDownloader);

Here we get

java.lang.IllegalArgumentException: This connector is not the parent for given extension at com.vaadin.server.AbstractClientConnector.removeExtension(AbstractClientConnector.java:595)

fileDownloader.removeExtension(downloadButton); 

and here we cannot apply Button to Extension

How can I reset FileDownloader for Button?


Solution

  • You extend download

        fileDownloader.extend(download);
    

    but try to remove the extension from fileDownloader

     downloadButton.removeExtension(fileDownloader);
    

    That is a mismatch. (Assuming that is a typo though.)

    You can remove the button and then create a new Button, a new downloader and then extend that. Some extensions can't be removed though.

    However, you don't need that. You can just update the StreamResource and not touch the binding at all.

    A more elaborate example is the OnDemandDownloader from https://vaadin.com/docs/v8/framework/articles/LettingTheUserDownloadAFile.html

         /**
         * This specializes {@link FileDownloader} in a way, such that both the file name and content can be determined
         * on-demand, i.e. when the user has clicked the component.
         */
        public class OnDemandFileDownloader extends FileDownloader {
    
          /**
           * Provide both the {@link StreamSource} and the filename in an on-demand way.
           */
          public interface OnDemandStreamResource extends StreamSource {
            String getFilename ();
          }
    
          private static final long serialVersionUID = 1L;
          private final OnDemandStreamResource onDemandStreamResource;
    
          public OnDemandFileDownloader (OnDemandStreamResource onDemandStreamResource) {
            super(new StreamResource(onDemandStreamResource, ""));
            this.onDemandStreamResource = checkNotNull(onDemandStreamResource,
              "The given on-demand stream resource may never be null!");
          }
    
          @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");
          }
        }