You need to use BrowserWindowOpener for that. You need to have a button or some other component, then create a BWO bound to the StreamResource, and call opener.extend(button).
See
this example for about exactly the case you have.
Hi Carmelo, you can try creating an Request Handler inside the UI Class.
I don’t know if this is the best solution to your problem, but this is my way to solve your problem. Sorry for my english, but not my native language.
new RequestHandler() { @Override
public boolean handleRequest(VaadinSession session,
VaadinRequest request,
VaadinResponse response)
throws IOException {
if (“/downloadFile”.equals(request.getPathInfo())) {
// if you want to use some parameter in your application
String param = request.getParameter(“yourFileName”);
response.setHeader(“Expires”, “0”);
response.setHeader(“Cache-Control”,“must-revalidate, post-check=0, pre-check=0”);
response.setHeader(“Pragma”, “public”);
response.setHeader(“Content-Disposition”, “attachment; filename="”+param+“"”);
response.setContentType(“application/pdf”);
OutputStream os = response.getOutputStream();
byte buffer = new byte[1024]
;
InputStream is = new FileInputStream(param);
int len;
while ((len = is.read(buffer)) > 0) {
os.write(buffer, 0, len);
}
is.close();
os.flush();
os.close();
return true;
} else
return false;
}
});
[/code]You can download your file using :
String url = "/yourApp/downloadFile?yourFileName=myfile.pdf";
Page.getCurrent().open(url,"_blank");
I hope that you find this useful.
Thank you for your answers, however I don’t want to download the pdf, but to open it on a new browser tab.
I also tried BrowserWindowOpener, but it did not work properly, because it listens for clicks only “after” the first button click…
Is it possible to get an URL from StreamResource? Maybe using properly ResourceReference? I tried with the following code but I get an error: <<HTTP Status 404 - /APP/connector/0/12/report/report.pdf can not be found. The requested resource is not available.>>
That example uses “two” buttons: the “OK” button for generating the report, and the “Open PDF” button to open it. But it’s a strange workflow… I should have one single button called “Print”. Have you got any idea?
You were saying on IRC that you need to click twice on the button for the new page to open with the report, and referenced this code:
http://pastebin.com/tQHMV6zi
You call BrowserWindowOpener.extend in the button’s click listener (through the helper class method stampaReport), which is the reason it won’t open the new window on the first click. You should just call AppUI.stampaReport(“report.jasper”, report.getId(), print); in the UI’s initialization.
The problem with it generating the report before you click the button is caused by line 44 of the paste:
resource.getStream().setParameter("Content-Disposition", "attachment;filename=\"report.pdf\"");
Calling StreamResource.getStream() also internally calls the associated StreamSource’s getStream method, because it is needed for the DownloadStream object’s constructor. Since you wish to open the resource in a new window, I assume you don’t wish it to be automatically downloaded, so you can remove the whole line, especially since I’m quite sure it doesn’t even do anything with BrowserWindowOpener.
Hi,
I’ve got different types of report, which should be printed on button click based on its type. So I cannot make calls in the UI’s initialization, because StreamResource is generated “after” button click, so I cannot have it before…
To display PDF document in Embedded frame, the browser must have support for PDF documents. Generally it requires a browser plugin, which may not be installed or even available for all browsers Hence, displaying embedded PDFs is not a good idea, except if the application is for an intranet, where you can configure workstations with the plugin, or if you use some embedded PDF viewer (which the Embedded component is not).
If you really have that requirement for internet apps (where you can’t rely on installed add-ons), I’d suggest looking for some embedded PDF viewer and integrating that with the Vaadin app. Some cloud services, such as Google Docs, offer an embedded PDF viewer.
Neeti Lakhotia:
Any help on how this needs to be done when we migrate to Vaadin 14
Assuming that you are using SpringBoot + Vaadin Flow 14 and that you have imported Jasper Libraries in Maven POM and that your reports (*.jasper) are in \app\src\main\resources\reports…
You may use IFrame instead of BrowserFrame, like this:
public void printReport(String reportName, HashMap<String, Object> params) {
final StreamResource resource = buildReport(reportName, params);
resource.setContentType("application/pdf");
resource.setCacheTime(0);
final StreamRegistration registration = VaadinSession.getCurrent().getResourceRegistry().registerResource(resource);
final IFrame content = new IFrame(registration.getResourceUri().toString());
content.setSizeFull();
final EnhancedDialog d = new EnhancedDialog();
d.setHeader(new H3("Report Viewer"));
d.setThemeVariants(EnhancedDialogVariant.SIZE_MEDIUM);
d.setModal(true);
d.setDraggable(false);
d.setResizable(false);
d.setHeight("90%");
d.setContent(content);
d.open();
d.addDialogCloseActionListener(e-> {registration.unregister(); d.close();} );
};
private StreamResource buildReport(String reportName, HashMap<String, Object> params) {
ResourceLoader loader = new DefaultResourceLoader();
Resource resource = loader.getResource(ResourceLoader.CLASSPATH_URL_PREFIX+"/reports/" + reportName);
byte[] b = null;
Connection conn = null;
try {
params.put("REPORT_DIRECTORY", resource.getFile().getParent());
conn = PgDatabaseService.getPoolDB().getConnection();
b = JasperRunManager.runReportToPdf(resource.getInputStream(), params, conn);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
conn.close();
} catch (SQLException e) {
}
}
InputStream is = new ByteArrayInputStream(b);
StreamResource myResource = new StreamResource("Report-"
+ UUID.randomUUID().toString().replace("-", "")
+ ".pdf", () -> is);
return myResource;
};
Neeti Lakhotia:
Any help on how this needs to be done when we migrate to Vaadin 14
Assuming that you are using SpringBoot + Vaadin Flow 14 and that you have imported Jasper Libraries in Maven POM and that your reports (*.jasper) are in \app\src\main\resources\reports…
You may use IFrame instead of BrowserFrame, like this:
public void printReport(String reportName, HashMap<String, Object> params) {
final StreamResource resource = buildReport(reportName, params);
resource.setContentType("application/pdf");
resource.setCacheTime(0);
final StreamRegistration registration = VaadinSession.getCurrent().getResourceRegistry().registerResource(resource);
final IFrame content = new IFrame(registration.getResourceUri().toString());
content.setSizeFull();
final EnhancedDialog d = new EnhancedDialog();
d.setHeader(new H3("Report Viewer"));
d.setThemeVariants(EnhancedDialogVariant.SIZE_MEDIUM);
d.setModal(true);
d.setDraggable(false);
d.setResizable(false);
d.setHeight("90%");
d.setContent(content);
d.open();
d.addDialogCloseActionListener(e-> {registration.unregister(); d.close();} );
};
private StreamResource buildReport(String reportName, HashMap<String, Object> params) {
ResourceLoader loader = new DefaultResourceLoader();
Resource resource = loader.getResource(ResourceLoader.CLASSPATH_URL_PREFIX+"/reports/" + reportName);
byte[] b = null;
Connection conn = null;
try {
params.put("REPORT_DIRECTORY", resource.getFile().getParent());
conn = PgDatabaseService.getPoolDB().getConnection();
b = JasperRunManager.runReportToPdf(resource.getInputStream(), params, conn);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
conn.close();
} catch (SQLException e) {
}
}
InputStream is = new ByteArrayInputStream(b);
StreamResource myResource = new StreamResource("Report-"
+ UUID.randomUUID().toString().replace("-", "")
+ ".pdf", () -> is);
return myResource;
};
thank you for this, it works fine! In my project I need to open doc/docx files as well as PDF files, but when i try to do so the dialog opens blank and the doc file downloads instantly. Could you help me to open these files like the pdf ones? I just cant figure it out…
Or if you could point me to another solution to do this would be great!
In my case I got pictures -which are docs/pdfs converted to images- in a view. When I click on the image it opens the file which it was saved to disk before.
finalImage.addClickListener((ClickEvent<Image> event) -> {
StreamResource streamResource = new StreamResource(imageName,
new InputStreamFactory() {
@Override
public InputStream createInputStream() {
try {
return new FileInputStream(path);
} catch (FileNotFoundException ex) {
Logger.getLogger(DocumentViewer.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
});
openDocumentDialog(streamResource);
});