Hi all and thanks for taking the time to answer my question.
I'm trying to send an array of bytes to the client so that his browser can reconstruct in e PDF file. Below is my code:
OutputStream out = response.getPortletOutputStream();
response.setProperty("Content-Disposition", "attachment; filename=" + fileName + ".pdf");
response.setContentType("application/pdf");
out.write(pdfInvoice);
out.flush();
out.close();
We're working with Liferay Portlets but that should not make a difference. pdfInvoice is the byte array. Nothing happens when this code executes. Can you spot what's wrong? Thanks in advance!
You can't serve a pdf in a Portlet response like that, the standard approach is to create a servlet which serves the PDF to the client.
If you want to serve the PDF inside a Portlet this guide should help http://www.liferay.com/community/wiki/-/wiki/Main/Generate+PDF+File+in+Portlet
Related
EDIT: The data I wanna send is in an rds. I fetch that into an output stream and then try to send it over as a pdf to the user.
The file gets generated but on opening the browser shows 'Failed to load PDF document.'
I have read that setting the ContentType to "application/pdf" helps but it does not in my case. The code is given below
byte[] b = generateFileService
.getDeviceHumidityRecordByPeriod(deviceIdValue, parseUnixTimestamp(startTime), parseUnixTimestamp(endTime));
OutputStream output = response.getOutputStream();
response.setContentType("application/pdf");
response.addHeader("Content-disposition", "attachment;filename=test.pdf");
output.write(b);
output.close();
response.flushBuffer();
}
if I change the file name to test.csv and then use content type as txt/plain, it works perfectly and a csv file is written.
I used Apache PDFBox to write data into a pdf file. The page offset needs to be tracked to add pages dynamically. Then you can convert the pdf into bytes and send it to the client by specifying response.setContentType("application/pdf") and response.addHeader("Content-disposition", "attachment;filename=test.pdf")
In my application using spring and angularjs and java, On clicking a button ,there is an ajax call which fetches the data from db and the data needs to be written to an excel file and the same file needs to be downloaded in the browser itself. I am attaching the code snippet for the same .
Now the problem is, even though the data is being fetched and I am able to bind it as worksheet using poi , the excel file never comes in the browser as download.
kindly help me in finding a right solution. Thank You.
fileName.append(Calendar.get(Calendar.SECOND));
fileName.append(oCalendar.get(Calendar.MILLISECOND));
Sheet sheet = workbook.createSheet("Transaction" + fileName.toString());
CellStyle style = workbook.createCellStyle();
style.setFont(font);
Row header = sheet.createRow(0);
header.createCell(0).setCellValue("Name");
header.createCell(1).setCellValue("ACC");
header.createCell(2).setCellValue("Date");
header.createCell(0).setCellValue("TRANSACTION_RECONCILIATION_IDENTIFIER");
header.createCell(1).setCellValue("ORIGINAL_RECONCILIATION_IDENTIFIER");
header.createCell(2).setCellValue("STR_TRANSACTION_Date");
response.setHeader("Content-Disposition", "attachment; filename=\"TransactionDetails.xls\"");
OutputStream outputStream = response.getOutputStream();
workbook.write(outputStream);
After writing the output stream you should use
response.flushBuffer();
Looks like you're missing the contentType definition. Before calling the write() method try setting the contentType like this:
response.setContentType("application/octet-stream");
This should tell the browser that a download is expected from the server. A relevant question was asked here: response.setContentType("APPLICATION/OCTET-STREAM")
In my code I write like this:
response.setContentType("application/octet-stream");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Content-Disposition",
"attachment; filename=TransactionDetails.xls");
workbook.write(response.getOutputStream());
Hope this helps
here i'm trying to read pdf file from server using java servlet. the below code i'm getting file path if file exists and then try to read file but,file does not open ?
String filePath = dirName;
String fileName = si + "_" + dnldFilename;
FileInputStream fileToDownload = new FileInputStream(filePath.concat(fileName);
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
response.setContentLength(fileToDownload.available());
int c;
while ((c = fileToDownload.read()) != -1) {
response.getOutputStream().write(c);
}
response.getOutputStream().flush();
response.getOutputStream().close();
fileToDownload.close();
The bug is here:
response.setContentLength(fileToDownload.available());
The InputStream#available() doesn't do what you (and the average Java starter) think. It doesn't return the total content length which is what the response header represents. It returns the amount of bytes available for reading without blocking all other threads (i.e. bytes which are currently already put in hardware buffer). If this is lower than the actual file size, then the client may simply stop reading the remainder of the response. In other words, the client got only a part of the PDF file, because you told the client that the desired part is of exactly the given length.
You need to construct a normal java.io.File and get the file size via File#length().
Here's a complete rewrite, reducing further legacy Java IO boilerplate too. This assumes you're on at least Java 7 (as Java 6 is EOL since 2013, no one would expect you're 2 years after date still at Java 6 anyway):
File file = new File(filePath, fileName);
response.setHeader("Content-Type", getServletContext().getMimeType(file.getName()));
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
Files.copy(file.toPath(), response.getOutputStream());
That's it. Do note that the above code snippet is this way reusable for all other kinds of files too. You can manage unknown content types via <mime-mapping> entries in web.xml.
Also note that I'm converting the content length to string as the setContentLength() takes only an int and File#length() returns long, which would fail if the file is larger than 2GB. In case you're on Servlet 3.1 (Tomcat 8, etc) already, make use of new setContentLengthLong() method.
response.setContentLengthLong(file.length());
See also:
Simplest way to serve static data from outside the application server in a Java web application
Abstract template for static resource servlet
Basically what I want to do is this : http://www.mkyong.com/java/how-to-export-data-to-csv-file-java/
Except at the end serve it as a download to the user.
Obviously I can't use FileWriter as I'm using JSF,but I tried doing something similar by getting the output stream from the external context and then making a buffered writer using the output stream(code below).According to my logs this does execute completely till the end,but no save as dialog pops up.I am using JSF 2(MyFaces) and RichFaces 4.3,if there is a better way to do this using a component please tell me.
externalContext.responseReset();
externalContext.setResponseHeader("Content-Disposition", "attachment; filename=test.csv");
externalContext.setResponseContentType("text/csv");
try {
OutputStream csvOut = externalContext.getResponseOutputStream();
BufferedWriter csvWriter = new BufferedWriter(new OutputStreamWriter(csvOut, "UTF-8"));
csvWriter.append("data,data,data,data");
csvWriter.flush();
csvWriter.close();
csvOut.close();
facesContext.responseComplete();
}catch(Exception ex){
System.out.println(ex.toString());
}
Any suggestions will help alot,been struggling with this for some time now.
Firstly thanks to uzvar for pointing me to Forcing a save as dialogue from any web browser from JSF application It's what helped me get mine working.
Basically all I did was instead of an OutputStream I declared an BufferedOutputStream with the externalContext.getResponseOutputStream(); as argument.So it looks like :
BufferedOutputStream csvOut = new BufferedOutputStream(externalContext.getResponseOutputStream());
The rest of the code stays the same.
If there is a better way to do this please post an answer/comment.
<%
response.reset();
response.setHeader("Content-Disposition", "attachment;filename=\"" + "test.xls\"");
response.setHeader("Content-Transfer-Encoding", "binary");
response.setContentType("application/vnd.ms-excel");
InputStream is = new FileInputStream(realPath);
//OutputStream outStream = response.getOutputStream();
JasperPrint jasperPrint = JasperFillManager.fillReport(is,
parameters, new JRBeanCollectionDataSource(pdfList));
JRAbstractExporter exporter = new JExcelApiExporter();
exporter.setParameter(JExcelApiExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JExcelApiExporterParameter.IS_DETECT_CELL_TYPE, Boolean.TRUE);
exporter.setParameter(JExcelApiExporterParameter.IS_WHITE_PAGE_BACKGROUND, Boolean.FALSE);
exporter.setParameter(JExcelApiExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS, Boolean.TRUE);
exporter.setParameter(JExcelApiExporterParameter.OUTPUT_STREAM, out);
exporter.exportReport();
outStream.flush();
outStream.close();
out.clear();
out =pageContext.pushBody();
%>
we use the code above to generate an excel, and it works well in tomcat + windows, but after we upload to linux + weblogic server, the excel is corrupted. I use text editor to open the excel, I found it add several empty line in the excel, which caused the excel can not be open successfully, anyone can point me the right direction ? Why there are space ? How it comes ?
Thanks in advance !
I suspect that your use of pageContext.pushBody() may be the culprit.
pushBody is, as far as I know, meant for updating the output in the scope of a JSP tag.
When you are generating binary content such as an excel file, where you need to be absolutely sure that the intended bytes, and only the intended bytes reach the browser, you need to write those bytes, flush the output, and then make sure that nothing else gets written. By invoking pushBody(), you are making it so that more content can be written to the output, and any blank lines (and the carriage returns / line feeds between them) in the JSP page could be output.
All in all, I suggest that you just not do this in a JSP - do it in a Servlet instead.