Generate Excel file using Java and Jasper - java

I am not sure what the Problem is, but I am generating an excel file using Java and Jasper Correctly, I want to Instantly download the file to client site in xlsx format but the file is downloading with .xhtml extension. What do I need to do? I am using JSF.
Here is My method:
public void generateOutStandingDCReportXLS() {
Connection conn = null;
try {
conn = db.getDbConnection();
Map parameters = new HashMap();
ClassLoader classLoader = getClass().getClassLoader();
InputStream logourl = classLoader.getResourceAsStream("/com/bi/jrxml/simba_logo.jpg");
InputStream stainurl = classLoader.getResourceAsStream("/com/bi/jrxml/coffee_stain.png");
parameters.put("logo", logourl);
parameters.put("stain", stainurl);
InputStream url = classLoader.getResourceAsStream("/com/bi/jrxml/Outstanding_DC.jrxml");
JasperReport jasperReport = JasperCompileManager.compileReport(url);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, conn);
ServletContext ctx = (ServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext();
String path = (String) ctx.getAttribute("reportdir");
File f = new File(path);
if (!f.exists()) {
f.mkdirs();
}
String reportDestination = f.getAbsolutePath() + "/OutStanding_DC_Report" + ".xlsx"; //This is generated Correctly
File xlsFile = new File(reportDestination);
JRXlsxExporter Xlsxexporter = new JRXlsxExporter();
Xlsxexporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
Xlsxexporter.setParameter(JRExporterParameter.OUTPUT_FILE, xlsFile);
Xlsxexporter.exportReport();//File is generated Correctly
FileInputStream fis = new FileInputStream(new File(reportDestination));
HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
IOUtils.copy(fis, response.getOutputStream());
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment; filename=" + "OutStanding_DC_Report" + ".xlsx"); //This is downloaded as .xhtml
response.flushBuffer();
fis.close();
} catch (JRException asd) {
System.out.println(asd.getMessage());
} catch (IOException asd) {
System.out.println(asd.getMessage());
} finally {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException asd) {
System.out.println(asd.getMessage());
}
}
}
The file on the server side is with the correct extension but the file getting downloaded has a .xhtml extension.

Call setContentType() and setHeader() before IOUtils.copy().
Once you call response.getOutputStream() the headers are sent.

Stanley, are you still facing the same issue?? if yes try to set below string in
response.setContentType()
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
i.e.
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
Instead of
application/vnd.ms-excel i.e. response.setContentType("application/vnd.ms-excel");
hope this will help.

Related

How can I change saving file directory?

I want to change saving file directory.
Here is it my code:
#RequestMapping(value = "/UploadFile")
public String uploadFile(HttpServletResponse response String base64, String name, String size) throws Exception {
byte[] decodedFile = Base64.getDecoder().decode(base64.getBytes(StandardCharsets.UTF_8));
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=" + name);
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
InputStream is = new ByteArrayInputStream(decodedFile);
IOUtils.copy(is, response.getOutputStream());
response.flushBuffer();
return "true";
}
Try this:
File path = new File("YOUR PATH HERE") ;
try (FileOutputStream fos = new FileOutputStream(path)) {
fos.write(decodedFile);
} catch (IOException e) {
e.printStackTrace();
}
You should also consider reading these links:
https://medium.com/javarevisited/how-to-upload-files-to-local-directory-in-spring-boot-c8c33f8239d3
https://spring.io/guides/gs/uploading-files/
EDIT
If String name is original File name, you could also do this:
File path = new File("C:\\YOUR_PATH\\images\\" + name);

PDF is rendered as text content when trying to view pdf file in my browser

I have an error when I want to download or see in the web browser a pdf file, somehow the file is generated in text. Has anyone had this problem?
Is my code:
public void downloadPDF(File ArchivoPDF, String NombrePDF) throws IOException{
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
BufferedInputStream input = null;
BufferedOutputStream output = null;
try{
input = new BufferedInputStream(new FileInputStream(ArchivoPDF),DEFAULT_BUFFER_SIZE);
response.reset();
response.setHeader("Content-Type","application/pdf");
response.setHeader("Content-Length",String.valueOf(ArchivoPDF.length()));
response.setHeader("Content-Disposition","attachment; filename=\"" + NombrePDF + ".pdf\"");
output = new BufferedOutputStream(response.getOutputStream(),DEFAULT_BUFFER_SIZE);
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int length;
while((length = input.read(buffer)) > 0){
output.write(buffer,0,length);
}
output.flush();
} finally{
close(output);
close(input);
}
facesContext.responseComplete();
}
private static void close(Closeable resource){
if(resource != null){
try{
resource.close();
} catch(IOException e){
e.printStackTrace();
}
}
}
and my component commandButton is:
<a4j:commandButton id="btnGenerarAllPDF" style="width:130px;"
rendered="#{clsGestionReclamoRealSrv.objComponente.blVerBtnGenerarExpedienteElectronico}"
value="Generar Expediente"
onclick="#{rich:component('modCargando')}.show();"
action="#{clsGestionReclamoRealSrv.doGenerarAllPDF}"
oncomplete="#{rich:component('modCargando')}.hide();"
reRender="frmRegistrarReclamo"/>
and call method in:
File ArchivoPDF = new File(pathFolderArch + String.valueOf(this.getObjReclamo().getNuIdReclamo()) + ".pdf");
if(ArchivoPDF.isFile()){
ClsUtils.deleteCarpeta(pathFolderTemp);
downloadPDF(ArchivoPDF,String.valueOf(this.getObjReclamo().getNuIdReclamo()));
} else {
logger.error("Error al generar el PDF.");
}
and the result is text in browser.
Text replace pdf
They know how to fix it.
I believe the appropriate way to set the content type is something like,
response.setContentType("Content-Type","application/pdf");
This could download your file as pdf as expected. To view the file in browser try something like,
response.setHeader("Content-Disposition", "inline; filename=\"" + NombrePDF + ".pdf\";");

java.lang.NoSuchMethodError: org.apache.poi.hssf.usermodel.HSSFWorkbook.getCreationHelper()Lorg/apache/poi/hssf/usermodel/HSSFCreationHelper;

Before I am using jasperreports-3.7.4 jar for downloading Jasper Reports in the form of Excel Format. Now I am trying to upgrade to jasperreports-6.3.1 jar. But it showing Error like "java.lang.NoSuchMethodError: org.apache.poi.hssf.usermodel.HSSFWorkbook.getCreationHelper()Lorg/apache/poi/hssf/usermodel/HSSFCreationHelper;" while calling exporterXLS.exportReport() method. I am using poi-3.6 jar also. Please provide solution to resolve this problem. Please find my code bellow.
handleDataBase db=null;
try {
OutputStream OutputStream = res.getOutputStream();
db = new handleDataBase();
Utility.comment("attra","before loading the Report "+new java.util.Date() + " - file name is "+reportFileName);
Connection connObj = db.getConnection();
//String jrPrint =JasperFillManager.fillReportToFile(jrxmlFile,params,connObj);
JasperPrint jasperPrint = JasperFillManager.fillReport(jrxmlFile, params, connObj);
Utility.comment("attra","After loading the Report "+new java.util.Date()+ " - file name is "+reportFileName);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
JRXlsExporter exporterXLS = new JRXlsExporter();
exporterXLS.setParameter(JRXlsExporterParameter.JASPER_PRINT,jasperPrint);
exporterXLS.setParameter(JRXlsExporterParameter.OUTPUT_STREAM,byteArrayOutputStream);
exporterXLS.setParameter(JRXlsExporterParameter.IS_COLLAPSE_ROW_SPAN, Boolean.TRUE);
exporterXLS.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_COLUMNS, Boolean.TRUE);
exporterXLS.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS, Boolean.TRUE);
//****************************Newly added by Shubham***************************************
exporterXLS.setParameter(JRXlsExporterParameter.IS_IGNORE_CELL_BORDER,Boolean.FALSE);
exporterXLS.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND, Boolean.FALSE);
exporterXLS.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET,Boolean.FALSE);
exporterXLS.setParameter(JRXlsExporterParameter.IS_DETECT_CELL_TYPE,Boolean.TRUE);
exporterXLS.setParameter(JRXlsExporterParameter.IS_IMAGE_BORDER_FIX_ENABLED,Boolean.TRUE);
exporterXLS.setParameter(JRXlsExporterParameter.IS_FONT_SIZE_FIX_ENABLED,Boolean.TRUE);
exporterXLS.setParameter(JRXlsExporterParameter.IS_IGNORE_GRAPHICS,Boolean.FALSE);
//***
exporterXLS.setParameter(JRXlsExporterParameter.IGNORE_PAGE_MARGINS,Boolean.TRUE);
//*****************************************************************************************
exporterXLS.exportReport();//**Here I am getting above error**
//To enable report to get downloaded in IE on an https connection
res.setHeader("Cache-Control", "public");
res.setHeader("Pragma", "public");
res.setHeader("Content-Disposition","filename=\"" + reportFileName + "\";");
res.setContentType("application/vnd.ms-excel");
OutputStream.write(byteArrayOutputStream.toByteArray());
OutputStream.flush();
OutputStream.close();
} catch (Exception e) {
Utility.comment("attra","Exception inside generateReport "+e.getMessage());
} finally{
db.close();
}
You may have to upgrade Apache POI to 3.8 or later. getCreationHelper() have been changed from:
public CreationHelper getCreationHelper() {
return new HSSFCreationHelper(this);
}
to:
public HSSFCreationHelper getCreationHelper() {
return new HSSFCreationHelper(this);
}
since 3.8.

Java HttpServlet how to download excel file

I am trying to add a function to my web app which lets the users download an excel file.
I'm trying to achieve this with the following code:
#Override
public void doPost(HttpServletRequest request, HttpServletResponse response) {
File file = new File("d:/test/test.xls");
response.setContentType("application/xls");
response.addHeader("Content-Disposition", "attachment; filename=test.xls");
response.setContentLength((int) file.length());
try {
FileInputStream fileInputStream = new FileInputStream(file);
OutputStream responseOutputStream = response.getOutputStream();
int bytes;
while ((bytes = fileInputStream.read()) != -1) {
responseOutputStream.write(bytes);
}
fileInputStream.close();
responseOutputStream.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I'm able to download the excel file with the above code, however the file is corrupted. If I open it with microsoft excel, I get a popup with the message:
"the file format and extension of don't match. the file could be corrupted or unsafe".
And the excel file is empty.
After running the code, the original file(d:/test/test.xls) gets also corrupted.
What am I doing wrong?
The official MIME type for Excel file .xls is application/vnd.ms-excel and for .xlsx is application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.
Also, I would suggest doing response.reset() prior to writing to the output stream and responseOutputStream.flush() (important) prior to closing the response.
Try below code :
File file = null;
InputStream in = null;
OutputStream outstream = null;
try {
response.reset();
in = new FileInputStream(file);
response.setContentType("application/vnd.ms-excel");
response.addHeader("content-disposition", "attachment; filename=data.xls");
outstream = response.getOutputStream();
IOUtils.copyLarge(in, outstream);
}
catch (Exception e) {
out.write("Unable to download file");
}finally {
IOUtils.closeQuietly(outstream);
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(out);
if (file != null)
file.delete();
}
dont forgot to add apache commons-io-2.4 in your dependency

Problems displaying PDF inside a new browser tab using a flex + servlet + jasper

I'm using my reportService class to generate the JasperPrint object that contains my report, then I send it to a Servlet and it generates the PDF. The problem is that this servlet is not opening the PDF in a new tab(this is what I want), actually it doesn't even prompting me to download it or anything.
Servlet Caller:
try {
URL url = new URL("http://" + serverName + ":" + serverPort + path
+ "/reportgenerator");
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setRequestMethod("POST");
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setDefaultUseCaches(false);
connection.setRequestProperty("Content-Type",
"application/octet-stream");
ObjectOutputStream out = new ObjectOutputStream(
connection.getOutputStream());
//This "jasperPrint" is my generated report from my service
out.writeObject(jasperPrint);
out.close();
connection.getInputStream();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
My doPost method from my Servlet:
#Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
JasperPrint jasperPrint = null;
ObjectInputStream resultStream = null;
ServletOutputStream out = response.getOutputStream();
try {
resultStream = new ObjectInputStream(request.getInputStream());
jasperPrint = (JasperPrint) resultStream.readObject();
resultStream.close();
byte[] rel = JasperExportManager.exportReportToPdf(jasperPrint);
out.write(rel,0, rel.length);
//JasperExportManager.exportReportToPdfStream(jasperPrint, out);
response.setContentLength(rel.length);
response.setContentType("application/pdf");
response.setHeader("Content-Disposition",
"attachment; filename=\"report.pdf\"");
response.setHeader("Cache-Control", "no-cache");
System.err.println(rel.length);
} catch (JRException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
out.flush();
out.close();
}
}
What am I doing wrong?
Assuming you have the byte[] of the file you want to open on the flex side of your application you should be able to write the file to a temp location and then open it. It would look similar to this:
//create a temp dir in the system temp directory to place all the temp files for you app.
private static var tempDir:File=File.createTempDirectory();
/**
* bytes - the byte array of the pdf you want to open
* filename - the name to use for the temp file, you may need to create some type of
* counter to add to the beginning of the filename so that you always get
* a unique name
*/
public static openFile(bytes:ByteArray,filename:String):void{
//create a file in the system temp directory to write the file to
var tempFile:File = tempDir.resolvePath(filename);
//create a filestream to write the byte array to the file
var fileStream:FileStream = new FileStream();
fileStream.open(tempFile, FileMode.WRITE);
fileStream.writeBytes(bytes,0,bytes.length);
fileStream.close();
//open the temp file with default application
tempFile.openWithDefaultApplication();
}
I've solved my problem returning the JasperPrint as a byte[] to my flex application, in flex it will be treated as a ByteArray(because it's converted by, in my case, graniteds) and then I just call my servlet sending this ByteArray.
I'm looking for another solution, but it can help someone else.

Categories

Resources