Download Excel file in browser using java - java

I have seen this question so many places, But still not able to solve my requirement.
I have written code to generate excelsheet in Apache POI in ADF using Java and need to download it in browser as application will be in server side not always in my local machine.
Initially I tried code:
Desktop.getDesktop().open(new File(home + "/Downloads/" + "excel1" + filename + ".xls"));
It was downloading. But it is downloading only on my machine. It's not downloading on other machine.
Another solution:
file = new File(home + "/Downloads/" + "excel" + filename + ".xls");
Runtime.getRuntime().exec("cmd.exe /C start " + file);
But it is not working..
Another solution:
FacesContext fc = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) fc.getExternalContext().getResponse();
response.reset();
response.setContentType(“application/vnd.ms-excel”);
response.setHeader(“Content-Disposition”, “attachment; filename=\"excel.xlsx");
workbook.write(response.getOutputStream());
fc.responseComplete();
But this solution also does not work.

I have a suggestion to try to solve your problem.
I usually create a servlet that has the responsibility of downloading files in various formats: xls, pdf...
Here is an example of how this can be done:
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class DownloadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String fileName = request.getParameter("fileName");
String contentType = null;
if (fileName.endsWith("xls")) {
contentType = "application/octet-stream";
} else if (fileName.endsWith("pdf")) {
contentType = "application/pdf";
} else {
throw new RuntimeException("File type not found");
}
byte[] file = getFileOnServer(fileName);
response.setHeader("Content-disposition", "attachment;filename=" + fileName);
response.setHeader("charset", "iso-8859-1");
response.setContentType(contentType);
response.setContentLength(file.length);
response.setStatus(HttpServletResponse.SC_OK);
OutputStream outputStream = null;
try {
outputStream = response.getOutputStream();
outputStream.write(file, 0, file.length);
outputStream.flush();
outputStream.close();
response.flushBuffer();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
private byte[] getFileOnServer(String fileName) {
//implement your method to get the file in byte[]
return null;
}
}
So, you can call your servlet by URL:
http://localhost:8080/downloadServlet?fileName=myExcel.xls
or Form:
<form id="myDownloadServlet" action="downloadServlet" method="post">
<input type="text" id="fileName" name="fileName" />
<input type="submit" id="btnDownload" name="btnDownload" value="Download File" />
</form>
Don't forget to configure your web.xml or use the annotation #WebServlet.
I hope I've helped.

A more "professional" solution is to use Excel Api's for java, as Apache POI or JXL.
Here an example using JXL:
https://www.java-tips.org/other-api-tips-100035/93-jexcel/418-how-do-i-output-an-excel-file-from-a-servlet.html
And here one more using Apache POI:
https://programtalk.com/java/download-excel-using-servlet/
I hope this can helps you.
Best wishes!

Related

xhtml to pdf servlet with flyingsaucer

I am trying to use flyingsaucer to serve pdf generated from xhtml but I am having trouble getting the servlet example to run.
All the other flyingsaucer examples work fine for me but I need this to work as a servlet to incorporate into a webapp.
The full code for the servlet is as follows:
import java.io.*;
import java.net.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.xhtmlrenderer.pdf.ITextRenderer;
public class PDFServlet extends HttpServlet {
protected void processRequest(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/pdf");
StringBuffer buf = new StringBuffer();
buf.append("<html>");
String css = getServletContext().getRealPath("/PDFservlet.css");
System.out.println("css url 2= " + css);
// put in some style
buf.append("<head><link rel='stylesheet' type='text/css' "+
"href='"+css+"' media='print'/></head>");
buf.append("<body>");
buf.append("<h1>Quarterly Reports for " +
request.getParameter("username")+"</h1>");
buf.append("<table cellspacing='0'>");
buf.append("<tr><th>Sales</th><th>Profit</th><th>Bonus</th></tr>");
// generate sales data
int totalSales = 0;
int totalProfit = 0;
int totalBonus = 0;
for(int i=0; i<10; i++) {
int currentSales = (int)(Math.random()*10000);
int currentProfit = (int)(currentSales*0.2);
int currentBonus = (int)(currentProfit*0.33);
buf.append("<tr><td>"+currentSales+"$</td><td>"+
currentProfit+"$</td><td>"+currentBonus+"$</td></tr>");
totalSales += currentSales;
totalProfit += currentProfit;
totalBonus += currentBonus;
}
buf.append("<tr class='total-header'><td colspan='3'>totals</td></tr>");
buf.append("<tr class='total'><td>"+totalSales+"$</td><td>"+
totalProfit+"$</td><td>"+totalBonus+"$</td></tr>");
buf.append("</table>");
buf.append("</body>");
buf.append("</html>");
byte[] byteArray = buf.toString().getBytes("ISO-8859-1");
// parse our markup into an xml Document
DocumentBuilder builder;
try {
builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
ByteArrayInputStream baos = new ByteArrayInputStream(byteArray);
Document doc = builder.parse(baos);
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(doc, null);
OutputStream os = response.getOutputStream();
renderer.layout();
renderer.createPDF(os);
os.flush();
os.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
public String getServletInfo() {
return "Short description";
}
}
I get this exception:
Jan 17, 2013 7:55:23 PM org.xhtmlrenderer.util.XRLog log
WARNING: Unhandled exception. IOException on parsing style seet from a Reader; don't know the URI.
java.io.IOException: Stream closed
at java.io.BufferedInputStream.getInIfOpen(Unknown Source)
at java.io.BufferedInputStream.read1(Unknown Source)
at java.io.BufferedInputStream.read(Unknown Source)
at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
at sun.nio.cs.StreamDecoder.read(Unknown Source)
at java.io.InputStreamReader.read(Unknown Source)
at org.xhtmlrenderer.css.parser.Lexer.zzRefill(Lexer.java:1527)
...
at org.xhtmlrenderer.context.StyleReference.readAndParseAll(StyleReference.java:122)
at org.xhtmlrenderer.context.StyleReference.setDocumentContext(StyleReference.java:106)
at org.xhtmlrenderer.pdf.ITextRenderer.setDocument(ITextRenderer.java:130)
at org.xhtmlrenderer.pdf.ITextRenderer.setDocument(ITextRenderer.java:106)
at PDFServlet.processRequest(PDFServlet.java:73)
at PDFServlet.doGet(PDFServlet.java:75)
...
It doesn't run beyond this line (in the try-catch block):
renderer.setDocument(doc, null);
I tried a few things like changing the input stream type and verifying that the xhtml ran OK but that did not resolve anything.
I am not all that familiar with Java servlets so I am not sure if I am addressing the right problem, it seems that I need to work out some way to keep the input stream from closing before I run this:
renderer.setDocument(doc, null);
Is this possible or should I be addressing something else?
I am using Tomcat 7 and Java 6. I noticed other people had a similar problem but I only get it when running the servlet example - all other examples run fine.
String css = getServletContext().getRealPath("/PDFservlet.css");
This is not right. It has to be an URL, not a local disk file system path. IText is attempting to download it by an URL "the usual way", like as a webbrowser would do.
One of the ways to construct the proper URL would be this:
StringBuffer url = req.getRequestURL();
String base = url.substring(0, url.length() - req.getRequestURI().length() + req.getContextPath().length());
String css = base + "/PDFservlet.css";

Start download from servlet via gwt (http get)

I would like to start a file download from a clickevent in my gwt web app. So I wrote a Servlet which writes the data to the output and should start the download. The data is received via http get.
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String data = request.getParameter("data");
String filename = request.getParameter("filename");
byte[] streamData = data.getBytes();
response.setContentType("application/force-download");
response.setHeader("Content-Disposition", "attachment; fileName="
+ filename + ".csv");
response.setContentLength(streamData.length);
ServletOutputStream out = response.getOutputStream();
out.write(streamData);
out.flush();
}
In the client I start the get method via requestBuilder.sendRequest():
RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.GET, /download");
requestBuilder.sendRequest("filename=dues&data="+ theDataAsString, new RequestCallback() {
#Override
public void onResponseReceived(Request request,
Response response) {
// Anything to do here?
}
#Override
public void onError(Request request, Throwable exception) {
exception.printStackTrace();
SC.warn("Error while creating export file.");
}
});
Nothing happens. But why? Shouldn't the browser ask to begin a download?
Does it, in this case, matter if i use post or get?
I don't want to use somthing like
Window.open("/download?data=myData&filename=filename", "_blank", "");
Any ideas?
On the client side, use an Anchor instead of a request builder and invoke the servlet directly.

InputStream from a URL

How do I get an InputStream from a URL?
for example, I want to take the file at the url wwww.somewebsite.com/a.txt and read it as an InputStream in Java, through a servlet.
I've tried
InputStream is = new FileInputStream("wwww.somewebsite.com/a.txt");
but what I got was an error:
java.io.FileNotFoundException
Use java.net.URL#openStream() with a proper URL (including the protocol!). E.g.
InputStream input = new URL("http://www.somewebsite.com/a.txt").openStream();
// ...
See also:
Using java.net.URLConnection to fire and handle HTTP requests
Try:
final InputStream is = new URL("http://wwww.somewebsite.com/a.txt").openStream();
(a) wwww.somewebsite.com/a.txt isn't a 'file URL'. It isn't a URL at all. If you put http:// on the front of it it would be an HTTP URL, which is clearly what you intend here.
(b) FileInputStream is for files, not URLs.
(c) The way to get an input stream from any URL is via URL.openStream(), or URL.getConnection().getInputStream(), which is equivalent but you might have other reasons to get the URLConnection and play with it first.
Your original code uses FileInputStream, which is for accessing file system hosted files.
The constructor you used will attempt to locate a file named a.txt in the www.somewebsite.com subfolder of the current working directory (the value of system property user.dir). The name you provide is resolved to a file using the File class.
URL objects are the generic way to solve this. You can use URLs to access local files but also network hosted resources. The URL class supports the file:// protocol besides http:// or https:// so you're good to go.
Pure Java:
urlToInputStream(url,httpHeaders);
With some success I use this method. It handles redirects and one can pass a variable number of HTTP headers asMap<String,String>. It also allows redirects from HTTP to HTTPS.
private InputStream urlToInputStream(URL url, Map<String, String> args) {
HttpURLConnection con = null;
InputStream inputStream = null;
try {
con = (HttpURLConnection) url.openConnection();
con.setConnectTimeout(15000);
con.setReadTimeout(15000);
if (args != null) {
for (Entry<String, String> e : args.entrySet()) {
con.setRequestProperty(e.getKey(), e.getValue());
}
}
con.connect();
int responseCode = con.getResponseCode();
/* By default the connection will follow redirects. The following
* block is only entered if the implementation of HttpURLConnection
* does not perform the redirect. The exact behavior depends to
* the actual implementation (e.g. sun.net).
* !!! Attention: This block allows the connection to
* switch protocols (e.g. HTTP to HTTPS), which is <b>not</b>
* default behavior. See: https://stackoverflow.com/questions/1884230
* for more info!!!
*/
if (responseCode < 400 && responseCode > 299) {
String redirectUrl = con.getHeaderField("Location");
try {
URL newUrl = new URL(redirectUrl);
return urlToInputStream(newUrl, args);
} catch (MalformedURLException e) {
URL newUrl = new URL(url.getProtocol() + "://" + url.getHost() + redirectUrl);
return urlToInputStream(newUrl, args);
}
}
/*!!!!!*/
inputStream = con.getInputStream();
return inputStream;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
Full example call
private InputStream getInputStreamFromUrl(URL url, String user, String passwd) throws IOException {
String encoded = Base64.getEncoder().encodeToString((user + ":" + passwd).getBytes(StandardCharsets.UTF_8));
Map<String,String> httpHeaders=new Map<>();
httpHeaders.put("Accept", "application/json");
httpHeaders.put("User-Agent", "myApplication");
httpHeaders.put("Authorization", "Basic " + encoded);
return urlToInputStream(url,httpHeaders);
}
Here is a full example which reads the contents of the given web page.
The web page is read from an HTML form. We use standard InputStream classes, but it could be done more easily with JSoup library.
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
<version>1.6</version>
</dependency>
These are the Maven dependencies. We use Apache Commons library to validate URL strings.
package com.zetcode.web;
import com.zetcode.service.WebPageReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#WebServlet(name = "ReadWebPage", urlPatterns = {"/ReadWebPage"})
public class ReadWebpage extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/plain;charset=UTF-8");
String page = request.getParameter("webpage");
String content = new WebPageReader().setWebPageName(page).getWebPageContent();
ServletOutputStream os = response.getOutputStream();
os.write(content.getBytes(StandardCharsets.UTF_8));
}
}
The ReadWebPage servlet reads the contents of the given web page and sends it back to the client in plain text format. The task of reading the page is delegated to WebPageReader.
package com.zetcode.service;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.apache.commons.validator.routines.UrlValidator;
public class WebPageReader {
private String webpage;
private String content;
public WebPageReader setWebPageName(String name) {
webpage = name;
return this;
}
public String getWebPageContent() {
try {
boolean valid = validateUrl(webpage);
if (!valid) {
content = "Invalid URL; use http(s)://www.example.com format";
return content;
}
URL url = new URL(webpage);
try (InputStream is = url.openStream();
BufferedReader br = new BufferedReader(
new InputStreamReader(is, StandardCharsets.UTF_8))) {
content = br.lines().collect(
Collectors.joining(System.lineSeparator()));
}
} catch (IOException ex) {
content = String.format("Cannot read webpage %s", ex);
Logger.getLogger(WebPageReader.class.getName()).log(Level.SEVERE, null, ex);
}
return content;
}
private boolean validateUrl(String webpage) {
UrlValidator urlValidator = new UrlValidator();
return urlValidator.isValid(webpage);
}
}
WebPageReader validates the URL and reads the contents of the web page.
It returns a string containing the HTML code of the page.
<!DOCTYPE html>
<html>
<head>
<title>Home page</title>
<meta charset="UTF-8">
</head>
<body>
<form action="ReadWebPage">
<label for="page">Enter a web page name:</label>
<input type="text" id="page" name="webpage">
<button type="submit">Submit</button>
</form>
</body>
</html>
Finally, this is the home page containing the HTML form.
This is taken from my tutorial about this topic.

JPEG file in WEB-INF returned as null by ServletContext#getResource()

Good day!
I am trying to output a JPG file contained in the web application to the
user using the following code:
public class JpegOutput extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
byte bufferArray[] = new byte[1024];
ServletContext ctxt = getServletContext();
response.setContentType("image/jpeg");
ServletOutputStream os = response.getOutputStream();
InputStream is = ctxt.getResource("/WEB-INF/image/image1.jpg").openStream();
int read = is.read(bufferArray);
while (read != 1) {
os.write(bufferArray);
read = is.read(bufferArray);
}
is.close();
os.close();
}
}
But an error appears:
HTTP Status 500 -
exception java.lang.NullPointerException
I am not sure if it can't read the source image or something. Anyway, I put the image inside this folder /WEB-INF/image/image1.jpg
What am I doing wrong? How can I resolve this issue?
EDIT: I solved the problem by renaming the filename... the file name is case sensitive, instead of image1.jpg, it should be image1.JPG
Thank you.
You might use getServletContext().getRealPath("/") to get the path to /WEB-INF/. E.g.
String path = getServletContext().getRealPath("/") + "WEB-INF/image/image1.jpg";
InputStream is = new FileInputStream(path);
Though its not sure that this is the reason for the NPE. Can you check the log file and post the stacktrace?
Not sure about the error, but I think it would be better to forward the request rather than serve the image manually:
public class JpegOutput extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/image/image1.jpg")
.forward(request, response);
}
}
Also note that you content-serving loop is incorrect, the correct one looks like this:
while ((read = is.read(bufferArray)) != -1)
os.write(bufferArray, 0, read);

Crystal Report DB authentication in java

I'm facing a problem in Crystal Report with Eclipse.
I am using a servlet to render the crystal report viewer by writing the viewer object to the response like:
public class ReportViewer extends HttpServlet {
#SuppressWarnings("deprecation")
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
String reportName = "WEB-INF/includes/reports/"+request.getParameter("ReportName");
ReportClientDocument clientDoc = (ReportClientDocument) request.getSession().getAttribute(reportName);
if (clientDoc == null) {
// Report can be opened from the relative location specified in the CRConfig.xml, or the report location
// tag can be removed to open the reports as Java resources or using an absolute path
// (absolute path not recommended for Web applications).
clientDoc = new ReportClientDocument();
// Open report
clientDoc.open(reportName, OpenReportOptions._discardSavedData);
// Store the report document in session
ConnectionInfo info = new ConnectionInfo();
info.setUserName("sa");
info.setPassword("sa");
Tables t = clientDoc.getDatabaseController().getDatabase().getTables();
for (com.crystaldecisions.sdk.occa.report.data.ITable table : t) {
IConnectionInfo Ic = table.getConnectionInfo();
Ic.setPassword("sa");
Ic.setUserName("sa");
table.setConnectionInfo(Ic);
}
request.getSession().setAttribute(reportName, clientDoc);
}
// Create the CrystalReportViewer object
CrystalReportViewer crystalReportPageViewer = new CrystalReportViewer();
// set the reportsource property of the viewer
IReportSource reportSource = clientDoc.getReportSource();
crystalReportPageViewer.setReportSource(reportSource);
// set viewer attributes
crystalReportPageViewer.setOwnPage(true);
crystalReportPageViewer.setOwnForm(true);
// Apply the viewer preference attributes
// Process the report
crystalReportPageViewer.processHttpRequest(request, response, request.getSession(false).getServletContext(), null);
} catch (ReportSDKExceptionBase e) {
System.out.println(e);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
When I am trying to request this servlet it redirects me to jdbc login page then it goes back to this servlet. I need to avoid jdbc login step by hardcoding it somewhere. please help me, every single comment will be appreciated.
Have you checked out the wiki over at https://wiki.sdn.sap.com/wiki/display/BOBJ/Crystal%20Reports%20Java%20%20SDK%20Samples
There are a JSP example you maybe could use:
<%# page import="com.crystaldecisions.sdk.occa.report.application.OpenReportOptions,
com.crystaldecisions.sdk.occa.report.application.ReportClientDocument,
com.crystaldecisions.sdk.occa.report.exportoptions.ReportExportFormat,
java.io.ByteArrayInputStream,
java.util.Calendar"
%><%
String reportPath;
String db_username;
String db_password;
ReportClientDocument reportClientDocument;
ByteArrayInputStream byteArrayInputStream;
byte[] byteArray;
int bytesRead;
reportPath = request.getParameter("report_path");
db_username = request.getParameter("db_username");
db_password = request.getParameter("db_password");
/*
* Instantiate ReportClientDocument and specify the Java Print Engine as the report processor.
* Open a rpt file.
*/
reportClientDocument = new ReportClientDocument();
reportClientDocument.setReportAppServer(ReportClientDocument.inprocConnectionString);
reportClientDocument.open(reportPath, OpenReportOptions._openAsReadOnly);
/*
* Set the database logon for all connections in main report.
*/
reportClientDocument.getDatabaseController().logon(db_username, db_password);
/*
* Retrieve PDF format of report and stream out to web browser.
*/
byteArrayInputStream = (ByteArrayInputStream) reportClientDocument
.getPrintOutputController().export(ReportExportFormat.PDF);
response.reset();
response.setHeader("Content-disposition", "inline;filename=crreport.pdf");
response.setContentType("application/pdf");
byteArray = new byte[1024];
while((bytesRead = byteArrayInputStream.read(byteArray)) != -1) {
response.getOutputStream().write(byteArray, 0, bytesRead);
}
response.getOutputStream().flush();
response.getOutputStream().close();
reportClientDocument.close();
%>

Categories

Resources