2014-02-21 86 views
4

我尝试使用功能的添加按钮,从外部资源Vaadin - 下载的文件/另存为

Button saveAsButton = new Button(); 
private FileDownloader fileDownloader; 
fileDownloader = new FileDownloader(new ExternalResource(........)); 
fileDownloader.extend(saveAsButton); 

下载文件时,此不为我工作:/ 没有错误在后台

+0

您的ExternalResource位于何处? – nexus

+0

文件在我的本地机器上,我也使用上传vaadin实施和所有作品正确 – PDS

回答

3

使用FileResource而不是ExternalResource。 为了提供用于下载的文件,下面已经证明:

Button btn = new Button("Download"); 
layout.addComponent(btn); 

Resource res = new FileResource(new File("/tmp/file.pdf")); 
FileDownloader fd = new FileDownloader(res); 
fd.extend(btn); 
+0

好吧,我会尝试:) – PDS

+0

我使用相对路径和获取错误(文件未找到:下载?fileId = 3174),我会尝试绝对路径。我使用 BrowserWindowOpener bwo = new BrowserWindowOpener(“/ download?fileId =”+ file.getFileId()); bwo.extend(button); 预览没有问题 – PDS

+0

@PDave它使我没有意义通过文件提供程序引用本地定位文件,就像您使用“下载?...”一样。FileResource在其构造函数中接受文件引用! – nexus

6

this link简称。 自定义文件下载程序可以为您提供此功能。这是自定义类和演示。使用AdvancedFileDownloader超过内置com.vaadin.server.FileDownloader的主要优势在于,您可以在每次点击按钮时更改文件路径。在FileDownloader中,一旦文件被设置,它就不能被改变,即一个按钮每次点击只能下载相同的文件。

AdvancedFileDownloader.java: -

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.io.InputStream; 
import java.util.logging.Logger; 

import com.vaadin.server.ConnectorResource; 
import com.vaadin.server.DownloadStream; 
import com.vaadin.server.FileDownloader; 
import com.vaadin.server.Resource; 
import com.vaadin.server.StreamResource; 
import com.vaadin.server.VaadinService; 
import com.vaadin.server.VaadinSession; 
import com.vaadin.server.StreamResource.StreamSource; 
import com.vaadin.server.VaadinRequest; 
import com.vaadin.server.VaadinResponse; 
import com.vaadin.ui.AbstractComponent; 

/** 
* an advanced file downloader 
* 
* @author visruth 
* 
*/ 
public class AdvancedFileDownloader extends FileDownloader { 

    /** 
    * 
    */ 
    private static final long serialVersionUID = 7914516170514586601L; 
    private static final boolean DEBUG_MODE = true; 

    private static final Logger logger = java.util.logging.Logger 
      .getLogger(AdvancedFileDownloader.class.getName()); 

    private AbstractComponent extendedComponet; 

    private AdvancedDownloaderListener dynamicDownloaderListener; 
    private DownloaderEvent downloadEvent; 

    public abstract class DownloaderEvent { 

     /** 
     * 
     * @return 
     */ 
     public abstract AbstractComponent getExtendedComponet(); 

     public abstract void setExtendedComponet(
       AbstractComponent extendedComponet); 

    } 

    public interface AdvancedDownloaderListener { 
     /** 
     * This method will be invoked just before the download starts. Thus, a 
     * new file path can be set. 
     * 
     * @param downloadEvent 
     */ 
     public void beforeDownload(DownloaderEvent downloadEvent); 
    } 

    public void fireEvent() { 
     if (DEBUG_MODE) { 
      logger.info("inside fireEvent"); 
     } 
     if (this.dynamicDownloaderListener != null 
       && this.downloadEvent != null) { 
      if (DEBUG_MODE) { 
       logger.info("beforeDownload is going to be invoked"); 
      } 
      this.dynamicDownloaderListener.beforeDownload(this.downloadEvent); 
     } 
    } 

    public void addAdvancedDownloaderListener(
      AdvancedDownloaderListener listener) { 
     if (listener != null) { 
      DownloaderEvent downloadEvent = new DownloaderEvent() { 

       private AbstractComponent extendedComponet; 

       @Override 
       public void setExtendedComponet(
         AbstractComponent extendedComponet) { 
        this.extendedComponet = extendedComponet; 
       } 

       @Override 
       public AbstractComponent getExtendedComponet() { 
        // TODO Auto-generated method stub 
        return this.extendedComponet; 
       } 
      }; 
      downloadEvent 
        .setExtendedComponet(AdvancedFileDownloader.this.extendedComponet); 
      this.dynamicDownloaderListener = listener; 
      this.downloadEvent = downloadEvent; 

     } 
    } 

    private static class FileResourceUtil { 

     private String filePath; 

     private String fileName = ""; 

     private File file; 

     public String getFilePath() { 
      return filePath; 
     } 

     public void setFilePath(String filePath) { 
      this.filePath = filePath; 
      file = new File(filePath); 

      if (file.exists() && !file.isDirectory()) { 
       fileName = file.getName(); 
      } 
     } 

     /** 
     * makes a stream resource 
     * 
     * @return {@code StreamResource} 
     */ 
     @SuppressWarnings("serial") 
     public StreamResource getResource() { 
      return new StreamResource(new StreamSource() { 

       @Override 
       public InputStream getStream() { 

        if (filePath != null && file != null) { 

         if (file.exists() && !file.isDirectory()) { 
          try { 
           return new FileInputStream(file); 
          } catch (FileNotFoundException e) { 
           e.printStackTrace(); 
           return null; 
          } 
         } else { 
          return null; 
         } 

        } 
        return null; 
       } 

      }, FileResourceUtil.this.fileName) { 
       @Override 
       public String getFilename() { 
        return FileResourceUtil.this.fileName; 
       } 

      }; 
     } 

    } 

    private FileResourceUtil resource; 

    private AdvancedFileDownloader(FileResourceUtil resource) { 

     super(resource == null ? (resource = new FileResourceUtil()) 
       .getResource() : resource.getResource()); 

     AdvancedFileDownloader.this.resource = resource; 
     System.out.println("created a new instance of resource : " + resource); 
    } 

    public AdvancedFileDownloader() { 
     this(null); 
    } 

    /** 
    * @return the current file path 
    */ 
    public String getFilePath() { 
     return resource.getFilePath(); 
    } 

    /** 
    * sets the path for the file for downloading 
    * 
    * @param filePath 
    *   path of the file, i.e. path + file name with extension 
    */ 
    public void setFilePath(String filePath) { 

     if (resource != null && filePath != null) { 
      this.resource.setFilePath(filePath); 
      ; 
     } 
    } 

    @Override 
    public boolean handleConnectorRequest(VaadinRequest request, 
      VaadinResponse response, String path) throws IOException { 


     if (!path.matches("dl(/.*)?")) { 
      // Ignore if it isn't for us 
      return false; 
     } 
     VaadinSession session = getSession(); 

     session.lock(); 
     AdvancedFileDownloader.this.fireEvent(); 

     DownloadStream stream; 

     try { 
      Resource resource = getFileDownloadResource(); 
      if (!(resource instanceof ConnectorResource)) { 
       return false; 
      } 
      stream = ((ConnectorResource) resource).getStream(); 

      if (stream.getParameter("Content-Disposition") == null) { 
       // Content-Disposition: attachment generally forces download 
       stream.setParameter("Content-Disposition", 
         "attachment; filename=\"" + stream.getFileName() + "\""); 
      } 

      // Content-Type to block eager browser plug-ins from hijacking 
      // the file 
      if (isOverrideContentType()) { 
       stream.setContentType("application/octet-stream;charset=UTF-8"); 
      } 

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

而且演示CODO运行。在此代码中,您必须提供用于下载文件的文件路径。当你点击下载按钮,以便该文件路径可以更改为下载不同的文件

package com.example.samplevaadin; 

import javax.servlet.annotation.WebServlet; 

import com.example.samplevaadin.ui.componet.custom.AdvancedFileDownloader; 
import com.example.samplevaadin.ui.componet.custom.AdvancedFileDownloader.AdvancedDownloaderListener; 
import com.example.samplevaadin.ui.componet.custom.AdvancedFileDownloader.DownloaderEvent; 
import com.vaadin.annotations.Theme; 
import com.vaadin.annotations.VaadinServletConfiguration; 
import com.vaadin.server.VaadinRequest; 
import com.vaadin.server.VaadinServlet; 
import com.vaadin.ui.Button; 
import com.vaadin.ui.Link; 
import com.vaadin.ui.TextField; 
import com.vaadin.ui.UI; 
import com.vaadin.ui.VerticalLayout; 

@SuppressWarnings("serial") 
@Theme("samplevaadin") 
public class DemoUI extends UI { 

    @WebServlet(value = "/*", asyncSupported = true) 
    @VaadinServletConfiguration(productionMode = false, ui = DemoUI.class) 
    public static class Servlet extends VaadinServlet { 
    } 

    @Override 
    protected void init(VaadinRequest request) { 

     final VerticalLayout layout = new VerticalLayout(); 
     layout.setMargin(true); 


     final TextField inputFilepathField = new TextField(); 
     inputFilepathField.setValue("/home/visruthcv/README.txt"); 
     inputFilepathField.setImmediate(true); 
     layout.addComponent(inputFilepathField); 

     Button downloadButton = new Button("Download Button"); 
     // or 
     Link downloadLink = new Link(); 
     downloadLink.setCaption("Download link"); 

     final AdvancedFileDownloader downloader = new AdvancedFileDownloader(); 
     downloader 
       .addAdvancedDownloaderListener(new AdvancedDownloaderListener() { 

        /** 
        * This method will be invoked just before the download 
        * starts. Thus, a new file path can be set. 
        * 
        * @param downloadEvent 
        */ 
        @Override 
        public void beforeDownload(DownloaderEvent downloadEvent) { 

         String filePath = inputFilepathField.getValue(); 

         downloader.setFilePath(filePath); 

         System.out.println("Starting downlad by button " 
           + filePath.substring(filePath.lastIndexOf("/"))); 
        } 

       }); 

     downloader.extend(downloadButton); 
     layout.addComponent(downloadButton); 

     final AdvancedFileDownloader downloaderForLink = new AdvancedFileDownloader(); 
     downloaderForLink 
       .addAdvancedDownloaderListener(new AdvancedDownloaderListener() { 

        /** 
        * This method will be invoked just before the download 
        * starts. Thus, a new file path can be set. 
        * 
        * @param downloadEvent 
        */ 
        @Override 
        public void beforeDownload(DownloaderEvent downloadEvent) { 

         String filePath = inputFilepathField.getValue(); 

         downloaderForLink.setFilePath(filePath); 
         System.out.println("Starting download by link " 
           + filePath.substring(filePath.lastIndexOf("/"))); 

        } 

       }); 

     downloaderForLink.extend(downloadLink); 
     layout.addComponent(downloadLink); 

     setContent(layout); 
    } 

} 

beforeDownload方法将被调用。

+0

在VMWare环境中使用AdvancedDownloader时,我看到损坏的下载。该文件被创建并存储在服务器磁盘上。下载到客户端的时间大部分时间是32k/64k,而不是46kB或77kB。任何人看到这个? –

+0

@AndréSchild在正常的服务器环境中工作正常吗?确保路径在下载时有效。您可以检查为: - 首先尝试使用包含超过64KB数据的示例文本文件,并尝试在'beforeDownload'方法本身中打印文件内容,并验证它打印所有内容。 – Visruth

+0

是的,它适用于非虚拟环境。该文件是动态生成的,并在传递文件名以下载文件之前使用Fileoutputstream和out.close()存储在磁盘上。 –

0

我有两种方法,并有一些参数。

void buttonClick(){ 
     File file = generateReportFile(); 
     if (file != null) { 
      sendConvertedFileToUser(file, branchName + "_" + sdf.format(new Date()) + ".xlsx"); 
     } 
} 

private File generateReportFile() { 

     File tempFile = null; 
     FileOutputStream fileOut = null; 

     try { 

      tempFile = File.createTempFile("tmp", ".xlsx"); 
      fileOut = new FileOutputStream(tempFile); 
      workbook.write(fileOut); 

     } catch (final IOException e) { 
      return null; 
     } finally { 
      if (tempFile != null) { 
       tempFile.deleteOnExit(); 
      } 
      try { 
       if (fileOut != null) { 
        fileOut.close(); 
       } 
      } catch (final IOException e) { 
       e.printStackTrace(); 
      } 
     } 

     return tempFile; 
    } 



private boolean sendConvertedFileToUser(final File fileToExport, final String exportFileName) { 

     UI ui = UI.getCurrent(); 
     TemporaryFileDownloadResource resource; 
     try { 
      resource = new TemporaryFileDownloadResource(ui, exportFileName, this.EXCEL_MIME_TYPE, fileToExport); 
      ui.getPage().open(resource, null, false); 
     } catch (final FileNotFoundException e) { 
      return false; 
     } 

     return true; 
    }