在Vaadin example of how to print a dynamically generated PDF中,他们采用两步法,首先点击OkButton
,然后点击PrintButton
。问题是他们打开PDF的代码依赖于创建一个新的BrowserWindowOpener
,然后扩展Print
ClickListener
中OKButton
的{{1}}按钮。换句话说,他们有:
okButton.addClickListener(new ClickListener()
{
@Override
public void buttonClick(ClickEvent event)
{
// Dynamically generate PDF - this is greatly simplified.
StreamResource pdfResource = new PdfStreamResource();
BrowserWindowOpener opener = new BrowserWindowOpener(pdfResource);
opener.extend(printButton);
}
}
这很棒,因为Print
按钮现已链接到BrowserWindowOpener
,当您点击PrintButton
时会立即打开窗口/标签。
我遇到的问题是我不想要OkButton
,我只想要PrintButton
。在这种情况下,我无法添加
printButton.addClickListener(new ClickListener()
{
@Override
public void buttonClick(ClickEvent event)
{
// Dynamically generate PDF - this is greatly simplified.
StreamResource pdfResource = new PdfStreamResource();
BrowserWindowOpener opener = new BrowserWindowOpener(pdfResource);
opener.extend(printButton);
}
}
在ClickListener
对于PrintButton
,因为您第一次点击它无法正常工作。然后我想到如果我在BrowserWindowOpener
之外的ClickListener
声明了PrintButton
,在使用虚拟资源的东西中链接ClickListener
和BrowserWindowOpener opener = new BrowserWindowOpener("");
opener.extend(printButton);
PrintClickListener printClickListener = new PrintClickListener(opener);
printButton.addClickListener(printClickListener);
的类中,该怎么办:
opener
然后将ClickListener
传递给printButton.addClickListener(new ClickListener()
{
@Override
public void buttonClick(ClickEvent event)
{
// Dynamically generate PDF - this is greatly simplified.
StreamResource pdfResource = new PdfStreamResource();
opener.setResource(pdfResource);
}
}
,以便我可以执行以下操作:
BrowserWindowOpener
但问题是第一次点击会生成一个空白页面。
我的问题是如何让示例工作,将动态生成的PDF推送到浏览器窗口,只有一个单一按钮。 ClickListener
的所有示例似乎总是使用两个按钮。在类层次结构中声明更高的示例对我来说不起作用,它始终是一个初始空白页。
最后,我希望能够在Enumerable.Any
内完成所有这一切,这与其他一切完全脱钩。
答案 0 :(得分:2)
摆脱BrowserWindowOpener
并使用UI.getPage().open()
查看您的pdf文件。
getUI().getPage().open(resource, "_blank", false);
请注意,不推荐使用此method。
从Vaadin 7.0.0开始,在页面中打开资源的功能已经被基于字符串URL的类似方法所取代。这是因为资源的使用在内存管理方面存在问题,并且在某些浏览器中具有安全功能。建议使用Link来开始下载。
不要认为只在一个按钮中使用BrowserWindowOpener
而不用黑客入侵JavaScript。
修改强> 我使用BrowserWindowOpener取得了预期的效果。每次请求BrowserWindowOpenerState时,我都扩展了类并添加了pdf生成。问题是我搜索了一个在点击之后和BrowserWindowOpener打开新标签之前调用的方法。我能找到的唯一方法是getState() - 并且只有当组件的状态是脏的时候。我还必须在覆盖getState方法中添加一个标志,因为:
setResource方法也调用了getState()方法,所以我有无限循环
仅在真正需要时生成pdf
public class BrowserWindowOpenerWithBeforeClick extends BrowserWindowOpener
{
private boolean pdfGenerated = false;
public BrowserWindowOpenerWithBeforeClick(String url)
{
super(url);
}
@Override
protected BrowserWindowOpenerState getState(boolean markAsDirty) {
if(!pdfGenerated){
StreamResource resource = ((RfgUI) UI.getCurrent()).getResource();
pdfGenerated = true;
this.setResource("url",resource);
}
return (BrowserWindowOpenerState) super.getState(markAsDirty);
}
public void setPdfGenerated(boolean generated){
this.pdfGenerated = generated;
}
}
主UI界面中的pdf生成:
void pdfgeneration(final VerticalLayout layout)
{
name.setValue("Slartibartfast");
final Button ok = new Button("OK");
ok.setId("ok-button");
final BrowserWindowOpenerWithBeforeClick bwo = new BrowserWindowOpenerWithBeforeClick("");
bwo.extend(ok);
name.addValueChangeListener(new ValueChangeListener()
{
@Override
public void valueChange(ValueChangeEvent event)
{
bwo.setPdfGenerated(false);
bwo.markAsDirty();
}
});
layout.addComponent(name);
layout.addComponent(ok);
}
getResource方法:
public StreamResource getResource()
{
StreamSource source = new MyPdfSource((String) name.getValue());
String filename = new Random().nextInt() + "pdf_printing_example.pdf";
StreamResource resource = new StreamResource(source, filename);
resource.setMIMEType("application/pdf");
resource.setCacheTime(0);
resource.getStream().setParameter("Content-Disposition", "attachment; filename=" + filename);
return resource;
}
请注意,每次生成新的pdf文件时都必须更改文件名以避免缓存问题。
答案 1 :(得分:1)
这个解决方案对我有用:
双解;在发生时,生成一个链接并开始下载客户端。也只工作生成链接点击下载,或在事件服务器端启动下载客户端,或点击按钮。
Vaadin 8 为动态流资源生成这个 url:
<块引用>http://localhost:8080/{warPath}/APP/connector/{uiID}/{componentID}/url/{fileName}
此代码段的作用是:单击按钮时,会创建一个 StreamSource,但此时未生成 InputStream。然后,创建一个链接或按钮组件并将其附加到单击按钮侦听器之外的任何组件。还创建了一个 BrowserWindowOpener,它扩展了 Link 或 Button。 BrowserWindowOpener 上的侦听器,当附加时,生成 StreamSource 动态链接并在新窗口中打开(请记住,在 vaadin 8 中,方法 Page.getCurrent().open(Resource, WindowName, openAsPopuo) 已弃用)。 最后,只有当生成的链接是请求时才会调用 strem (getStream())。
VerticalLayout vlay = new VerticalLayout();
setCompositionRoot(vlay);
Button butt = new Button("Click");
vlay.addComponent(butt);
butt.addClickListener(evt->{
StreamSource ss = new StreamResource.StreamSource() {
private static final long serialVersionUID = 1L;
@Override
public InputStream getStream() {
return new ByteArrayInputStream("Qualsiasi byte array".getBytes());
}
};
StreamResource sr = new StreamResource(ss,"testo.txt");
sr.setMIMEType("application/octet-stream");
sr.setCacheTime(1l);
//Button downlButt = new Button("Download");
Link lnk = new Link("Download",null);
BrowserWindowOpener bwo = new BrowserWindowOpener(sr);
//bwo.extend(downlButt);
bwo.extend(lnk);
bwo.addAttachListener(attevt->{
String generatedURL = ApplicationConstants.APP_PATH+"/"+ConnectorResource.CONNECTOR_PATH+"/"+
UI.getCurrent().getUIId()+"/"+attevt.getConnector().getConnectorId()+"/"+
BrowserWindowOpenerState.locationResource+"/"+sr.getFilename();
Page.getCurrent().open(generatedURL, "_blank");
});
vlay.addComponent(lnk);
});