How to display DynamicReports in browser without download to cliend drive? - java

I have to display some reports with Dynamic Reports. I use NetBeans and Tomcat 7. Eventually, all must be uploaded to cloud OpenShift. I used DynamicReports to create simple report (code snippet):
Connection conn=null;
try {
Class.forName(DBConnStrings.driver);
conn = DriverManager.getConnection(DBConnStrings.url + DBConnStrings.dbName+DBConnStrings.sslState, DBConnStrings.userName, DBConnStrings.password);
} catch (Exception e) {
e.printStackTrace();
}
JasperReportBuilder report = DynamicReports.report();
report
.columns(
Columns.column("Tank Id", "id", DataTypes.integerType()),
Columns.column("Tank Name", "name", DataTypes.stringType()),
Columns.column("Label", "label", DataTypes.stringType()),
Columns.column("Description", "descrshort", DataTypes.stringType()));
report.setDataSource("SELECT id, name, label, descrshort FROM "+ DBConnStrings.dbName +".tbltankslist", conn);
try {
//show the report
//report.show();
//export the report to a pdf file
report.toPdf(new FileOutputStream("c:/report.pdf"));
} catch (DRException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
This code located in a Servlet. It works. I get JasperViewer at first and a report.pdf on my HDD. But I don't want it. First I do not want to see JasperViewer, second I do not want to download file to client HDD. How to display report inside web-browser only?
Here is the question Jasper Reports. It is about jasper reports + iReport and I have no idea how to use that information for DynamicReports - at first, second there is also "download pdf to client drive" approach, but I need to show it inside the browser.

use the following code in your file which redirect towards jasper invocation page, so that your jasperPDF should open in new tab instead of downloading.
JasperInvocation.jsp => file in which you invoke jasperReport
<form method="POST" action="JasperInvocation.jsp" target="_blank">

Please find following code , I have implemented in Dynamic report(Jasper Api) , Its working for me :-
#RequestMapping(value="/pdfDownload", method = RequestMethod.GET)
public void getPdfDownload(HttpServletResponse response) {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
report().columns().setDataSource().show()
.toPdf(buffer);
byte[] bytes = buffer.toByteArray();
InputStream inputStream = new ByteArrayInputStream (bytes);
IOUtils.copy(inputStream, response.getOutputStream());
response.setHeader("Content-Disposition", "attachment; filename=Accepted1.pdf");
response.flushBuffer();
}

Related

Can static content on spring-boot-web application be dynamic (refreshed)?

I am still searching around this subject, but I cannot find a simple solution, and I don't sure it doesn't exist.
Part 1
I have a service on my application that's generating an excel doc, by the dynamic DB data.
public static void
notiSubscribersToExcel(List<NotificationsSubscriber>
data) {
//generating the file dynamically from DB's data
String prefix = "./src/main/resources/static";
String directoryName = prefix + "/documents/";
String fileName = directoryName + "subscribers_list.xlsx";
File directory = new File(directoryName);
if (! directory.exists()){
directory.mkdir();
// If you require it to make the entire directory path including parents,
// use directory.mkdirs(); here instead.
}
try (OutputStream fileOut = new FileOutputStream(fileName)) {
wb.write(fileOut);
fileOut.close();
wb.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Part 2
I want to access it from the browser, so when I call it will get downloaded.
I know that for the static content, all I need to do is to call to the file, from the browser like that:
http://localhost:8080/documents/myfile.xlsx
After I would be able to do it, all I need is to create link to this url from my client app.
The problem -
Currently if I call to the file as above, it will download only the file which have been there in the compiling stage, but if I am generating a new files after the app is running the content won't be available.
It seems that the content is (as it's called) "static" and cannot be changed after startup.
So my question is
is there is a way to define a folder on the app structure that will be dynamic? I just want to access the new generated file.
BTW I found this answer and others which doing configuration methods, or web services, but I don't want all this. And I have tried some of them, but the result is the same.
FYI I don't bundle my client app with the server app, I run them from different hosts
The problem is to download the file with the dynamic content from a Spring app.
This can be solved with Spring BOOT. Here is the solution as shown in this illustration - when i click Download report, my app generates a dynamic Excel report and its downloaded to the browser:
From a JS, make a get request to a Spring Controller:
function DownloadReport(e){
//Post the values to the controller
window.location="../report" ;
}
Here is the Spring Controller GET Method with /report:
#RequestMapping(value = ["/report"], method = [RequestMethod.GET])
#ResponseBody
fun report(request: HttpServletRequest, response: HttpServletResponse) {
// Call exportExcel to generate an EXCEL doc with data using jxl.Workbook
val excelData = excel.exportExcel(myList)
try {
// Download the report.
val reportName = "ExcelReport.xls"
response.contentType = "application/vnd.ms-excel"
response.setHeader("Content-disposition", "attachment; filename=$reportName")
org.apache.commons.io.IOUtils.copy(excelData, response.outputStream)
response.flushBuffer()
} catch (e: Exception) {
e.printStackTrace()
}
}
This code is implemented in Kotlin - but you can implement it as easily in Java too.

Send file in response without downloading it

I have tried to build a http server to streaming video using HLS. I have process the response like below.
private void handleResponse(HttpExchange exchange, String fileNameValue) {
OutputStream responseStream = exchange.getResponseBody();
File file = new File(fileNameValue);
try {
String encoding = "UTF-8";
String response = FileUtils.readFileToString(file, encoding);
exchange.getResponseHeaders().set("Content-Type", "application/x-mpegURL");
exchange.getResponseHeaders().set("Accept-Ranges", "bytes");
exchange.getResponseHeaders().set("Cache-Control", "max-age=0, no-cache, no-store");
exchange.sendResponseHeaders(200, response.length());
responseStream.write(response.getBytes());
responseStream.flush();
responseStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
But the browsers always download the file instead of playing it. And VLC Media Player doesn't play it too.
I want to get the result like this.
Can you show me the way to do it? Some keywords for researching are also appreciated.
I have figured out that their website using xhr to send request so the file appears in the Network section.
I use hls.js after that and get the same result :)

Page's HTML code written into file when file is downloaded from web app

I have a downloadfile servlet code that will dynamically add contents into a CSV file for users to download. However instead of having the contents I want added into the CSV file, the page's HTML code appears in the file instead. Can anyone tell me what is causing this bug? Here's my controller code
response.setContentType("text/csv");
response.setHeader("Content-Disposition", "attachment";
filename="\\evaluations.csv\\");
try
{
OutputStream outputStream = response.getOutputStream();
String outputResult = "xxxx, yyyy, zzzz, aaaa, bbbb, ccccc, dddd, eeee, ffff, gggg\n";
outputStream.write(outputResult.getBytes());
outputStream.flush();
outputStream.close();
} catch(Exception e) {
status = "Error exporting file, please try again later";
System.out.println(e.toString());
}
//request.setAttribute("status",status);
//dispatcher = request.getRequestDispatcher("/viewEvaluations.jsp");
//dispatcher.forward(request, response);
EDIT:
Removing the forward request actually stop the HTML code from being copied into the file and I also realized its redundant and I've commented them out. This was the code that was causing the problem.
Well if you just want to reload the current page then you can do a trick:
Your <a> tag should be like this:
Click Here
In Jquery:
$('#test').click(function()
{
location.href='download'; //your download request mapping
setTimeout(function(){location.reload()},2000); //this will reload the current page after 2 seconds.
});
Your controller code will be:
#RequestMapping(value = "download", method = RequestMethod.GET)
public void download(Locale locale, Model model,HttpServletRequest request,HttpServletResponse response,HttpSession session) {
response.setContentType("text/csv");
response.setHeader("Content-disposition", "attachment; filename=evaluations.csv");
try
{
OutputStream outputStream = response.getOutputStream();
String outputResult = "xxxx, yyyy, zzzz, aaaa, bbbb, ccccc, dddd, eeee, ffff, gggg\n";
outputStream.write(outputResult.getBytes());
outputStream.flush();
outputStream.close();
} catch(Exception e) {
//logging
}
}
If you want to make visible an div which is hidden on page load then rather than calling location.reload() u should call $('#divId').show()

Generating pdf with wkhtmltopdf and download the pdf

I am working in a old project.The project is in Spring MVC .In the project I have to generate a pdf file from a jsp page and store in a location and download that file. For that I am using wkhtmltopdf tool to convert the one specific jsp page into pdf format. Using wkhtmltopdf sometime works fine, it generate the pdf in specific location, but sometime it require more time. Also when I am trying to download the file from specific location , sometime it download a 0KB size file or sometime the downloaded file can't be open (with some size) but sometime download perfectly. If I check the file at define location, it exist and open normally.
Here is my code in controller class.
#RequestMapping(value="/dwn.htm",method=RequestMethod.GET)
public void dwAppFm(HttpSession session,HttpServletRequest request,HttpServletResponse response,#RequestParam String id) throws IOException,InterruptedException
{
final int BUFFER_SIZES=4096;
ServletContext context=request.getServletContext();
String savePath="/tmp/";//PDF file Generate Path
String fileName="PDFFileName"; //Pdf file name
FileInputStream inputStream=null;
BufferedInputStream bufferedInputStream=null;
OutputStream outputStream=null;
printApp(id,fileName);
Thread.sleep(1000);
printApp(id,fileName);
File download=new File(savePath+fileName+".pdf");
while(!download.canRead())
{
Thread.sleep(1000);
printApp(id,fileName);
download=new File(savePath+fileName+".pdf");
}
if(download.canRead()){//if the file can read
try{
Thread.sleep(1000);
inputStream=new FileInputStream(download);
bufferedInputStream=new BufferedInputStream(inputStream);
String mimeType = context.getMimeType(savePath+fileName+".pdf");
if (mimeType == null) {
mimeType = "application/octet-stream";
}
System.out.println("MIME type: " + mimeType);
response.setContentType(mimeType);
response.setContentLength((int)download.length());
String headerKey="Content-Disposition";
String headerValue=String.format("attachment;filename=\"%s\"", download.getName());
response.setHeader(headerKey, headerValue);
outputStream=response.getOutputStream();
byte[] buffer=new byte[BUFFER_SIZES];
int bytesRead=-1;
while ((bytesRead = bufferedInputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
}catch(Exception e)
{
e.printStackTrace();
}
finally
{
try{
if(inputStream!=null)inputStream.close();
if(bufferedInputStream!=null)bufferedInputStream.close();
if(outputStream!=null)outputStream.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}
public void printApp(String id,String fileName)
{
try{
String urlPath="http://localhost:8080/proj";
urlPath+="/genApp.htm?id="+id;//generate url to execute wkhtmltopdf
String wxpath="/home/exm/wkhtmltopdf";//the path where wkhtmltopdf located
String save="/tmp/"+fileName+".pdf";//File save Pathname
Process process=null;
process=Runtime.getRuntime().exec(wxpath+" "+urlPath+" "+save);
}catch(Exception e)
{}
}
#RequestMapping(value="/genApp.htm",method=RequestMethod.GET)
public String getApplicationPDF(HttpServletRequest request,HttpSession session,#RequestParam String id)
{
UDets uDets=uService.getAllById(Long.parseLong(id));//Methods to get details
request.setAttribute("uDets",uDets );
return "makeApp";//Name of the jsp page
}
In my code I have use Thread.sleep(1000) and printApp(id,fileName) method three times , since sometime wkhtmltopdf fail to generate pdf in certain time and then probability of downloading 0KB file is more. I haven't share the jsp page since the jsp page contain simple jsp page code of lots of line (the size of the generated pdf file is two page).
So the problem is what should I change in my code so that the pdf file generated and download without a failure also in heavy load in server.
If there is any best procedure or idea please share.
I don't like to use itext, since the jsp page contain complex design. Any advise is also appreciable and also thanks in advance.
I would say that your code is flawed not just a little but big time. You are checking if a file can be read, if not you start again a proces writing to the same file (at least twice). At some time you will endup with multiple processes trying to write to the same file, resulting in strange behavior.
I would refactor the printApp method to return the Process it created. Then call waitFor on that process. If it returns 0 and doesn't get interrupted it completed successfully and you should be able to download the file.
#RequestMapping(value="/dwn.htm",method=RequestMethod.GET)
public void dwAppFm(HttpSession session,HttpServletRequest request,HttpServletResponse response,#RequestParam String id) throws IOException,InterruptedException
{
String savePath="/tmp/";//PDF file Generate Path
String fileName="PDFFileName.pdf"; //Pdf file name
File download = new File(savePath, fileName);
try {
Process process = printApp(id, download.getPath());
int status = process.waitFor();
if (status == 0) {
response.setContentType("application/pdf");
response.setContentLength((int)download.length());
String headerKey="Content-Disposition";
String headerValue=String.format("attachment;filename=\"%s\"", download.getName());
StreamUtils.copy(new FileInputStream(download), response.getOutputStream())
} else {
// do something if it fails.
}
} catch (IOException ioe) {
// Do something to handle exception
} catch (InterruptedException ie) {
// Do something to handle exception
}
}
}
public Process printApp(String id, String pdf) throws IOException {
String urlPath="http://localhost:8080/proj";
urlPath+="/genApp.htm?id="+id;//generate url to execute wkhtmltopdf
String wxpath="/home/exm/wkhtmltopdf";//the path where wkhtmltopdf located
String command = wxpath+" "+urlPath+" "+pdf;
return Runtime.getRuntime().exec(command);
}
Something like the code above should to the trick.

pdf download dialog window not appear in browser. extjs 4 with java

I am able to generate a report in pdf form using JasperReports and Java.
The generated report is not available to be downloaded to the client side.
I am generating pdf file using the code below:
public void getTaskreportPDF(Session openSession,HttpServletRequest request,HttpServletResponse response) {
try {
Class.forName("com.mysql.jdbc.Driver");
Connection con = (Connection) DriverManager.getConnection("jdbc:mysql://localhost/contact","root","root");
Map params = getParameters(openSession);
Date date = new Date();
String reportfileName = "report"+date.getDate()+"-"+date.getMonth()+"-"+date.getYear()+"-"+date.getTime()+".pdf";
JasperDesign jasperDesign = JRXmlLoader.load(this.getClass().getResourceAsStream("/com/gantt/report/ganttreport.jrxml"));
JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
JasperPrint jasperprint = JasperFillManager.fillReport(jasperReport, params,con);
JRAbstractExporter exporterPDF = new JRPdfExporter();
exporterPDF.setParameter(JRExporterParameter.JASPER_PRINT, jasperprint);
exporterPDF.setParameter(JRExporterParameter.OUTPUT_STREAM, response.getOutputStream());
response.setHeader("Content-Disposition", "inline;filename="+ reportfileName);
response.setContentType("application/pdf");
exporterPDF.exportReport();
} catch(Exception exception) {
System.out.println("Error occured " +exception.getMessage());
}
}
My firebug net tab shows that I had got the pdf report file of 4 kb as response. But the problem is that download window not appear, so I cannot save it or view that report.
My firebug shows:
Content-Disposition inline;filename=report21-0-112-1327135412907.pdf
Content-Type application/pdf
What mistake I am making which makes my download window not to appear?
Use attachment instead of inline for the Content-Disposition header.

Categories