Can't get HttpServletResponse from a portlet - jsf

I tried the following code :
PortletResponse response1 = (PortletResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse();
HttpServletResponse response = (HttpServletResponse)response1;
In a previous question the answer was to PortalUtil.getHttpServletResponse(portletResponse)
but the problem is that null pointer exception on response.getOutputStream()My full code is
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
//here is my code
PortletResponse portalResponse = (PortletResponse) externalContext.getResponse();
HttpServletResponse response = PortalUtil.getHttpServletResponse(portalResponse);
File file = new File(getFilePath(), getFileName());
BufferedInputStream input = null;
BufferedOutputStream output = null;
try {
input = new BufferedInputStream(new FileInputStream(file), DEFAULT_BUFFER_SIZE);
response.reset();
response.setHeader("Content-Type", "application/pdf");
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "inline; filename=\"" + getFileName() + "\"");
//here where nullException is returned from response.getOutputStream()
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();
which is written by #BalusC in
pdf-handling
My question is how to get this response in a portlet

Related

Timeout when generate excel for download

I am trying to export Excel using poi and servlet. code like this
SXSSFWorkbook workbook = genrateExcel(id)
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
workbook.write(outputStream);
byte[] outArray = outputStream.toByteArray();
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setContentLength(outArray.length);
response.setHeader("Expires:", "0");
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(excelFileName, "UTF-8"));
OutputStream outStream = response.getOutputStream();
outStream.write(outArray);
outStream.flush();
workbook.dispose();
workbook.close();
But sometimes generating costs too much time,so i get a 504 timeout error.
I wonder how can I hold the connection until file is generated ?
UPDATE:
thanks Gagravarr. I update the code to this
ExecutorService threadPool = Executors.newSingleThreadExecutor();
Future<SXSSFWorkbook> future = threadPool.submit(new Callable<SXSSFWorkbook>() {
#Override
public SXSSFWorkbook call() {
return genrateExcel(id);
}
});
SXSSFWorkbook workbook = null;
try {
response.setHeader("Expires:", "0");
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(excelFileName, "UTF-8"));
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
OutputStream outStream = response.getOutputStream();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
int times = 0;
while (times < 50) {
if (future.isDone()) {
workbook = future.get();
break;
}
outStream.flush();
Thread.sleep(5000);
times++;
}
workbook = workbook == null ? new SXSSFWorkbook() : workbook;
workbook.write(outputStream);
byte[] outArray = outputStream.toByteArray();
response.setContentLength(outArray.length);
outStream.write(outArray);
outStream.flush();
workbook.dispose();
workbook.close();
} catch (Exception e) {
e.printStackTrace();
}
But got a ClientAbortException: java.io.IOException meanwhile Chrome report the page isnot working ERR_INCOMPLETE_CHUNKED_ENCODING is sth wrong?

why downloading to file is not working in jsf? [duplicate]

This question already has answers here:
How to provide a file download from a JSF backing bean?
(5 answers)
Closed 5 years ago.
i made a call to download() method to save json into xml with extension ".svg". The jsondata is global variable store json.
public void download(){
File file = exportFile(jsondata);
HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
writeOutContent(response, file, file.getName());
FacesContext.getCurrentInstance().responseComplete();
FacesContext.getCurrentInstance().renderResponse();
}
and the exportFile(jsondata) is
public File exportFile(String jsonData){
File xmlFile = null;
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
JSONObject jsonObject = new JSONObject(jsonData);
Element root = doc.createElement("web");
doc.appendChild(root);
Element rootElement1 = doc.createElement("class");
rootElement1.appendChild(doc.createTextNode(jsonObject.getString("class")));
root.appendChild(rootElement1);
JSONArray jsonArray1 = (JSONArray) jsonObject.get("nodes");
Element rootElement2 = doc.createElement("nodes");
root.appendChild(rootElement2);
for (int i = 0; i < jsonArray1.length(); i++) {
Element staff = doc.createElement("node");
rootElement2.appendChild(staff);
JSONObject childObject = (JSONObject) jsonArray1.get(i);
Iterator<String> keyItr = childObject.keys();
while (keyItr.hasNext()) {
String key = keyItr.next();
Element property = doc.createElement(key);
property.appendChild(doc.createTextNode(childObject.getString(key)));
staff.appendChild(property);
}
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
//for pretty print
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
DOMSource source = new DOMSource(doc);
xmlFile = new File("file.svg");
//write to console or file
// StreamResult console = new StreamResult(System.out);
StreamResult file = new StreamResult(xmlFile);
//write data
// transformer.transform(source, console);
transformer.transform(source, file);
} catch (Exception pce) {
pce.printStackTrace();
}
return xmlFile;
}
finally to write this one file writeOutContent()
public void writeOutContent(final HttpServletResponse res, final File content, final String theFilename) {
if (content == null) {
System.out.println("content is null");
return;
}
try {
res.setHeader("Content-Disposition", "attachment; filename=\"" + theFilename + "\"");
System.out.println("res " + res.getHeader("attachment; filename=\"" + theFilename + "\""));
res.setContentType("application/octet-stream");
FileInputStream fis = new FileInputStream(content);
OutputStream os = res.getOutputStream();
int bt = fis.read();
while (bt != -1) {
os.write(bt);
bt = fis.read();
}
os.flush();
fis.close();
os.close();
} catch (Exception ex) {
Logger.getLogger(DownloadFile.class.getName()).log(Level.SEVERE, null, ex);
}
}
i can see the xml in console but what am doing wrong that its not downloading?? please help me.
thanks in advance.
i got the mistake. it was not in above code. if we make through commandLink then it won't work but if make call through commandButton then it worked. if you want know know more read difference between commandButton vs commandLink

How to open a PDF file in a new tab

I am working with JSF and I want to open a PDF file in a new tab when I click on a button.
XHTML
<p:commandButton onclick="this.form.target = '_blank'"
actionListener="#{managedBean.openFile(file)}"
ajax="false" />
Managed bean
public void openFile( File file ) {
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
BufferedInputStream input = null;
BufferedOutputStream output = null;
try {
// Open file.
input = new BufferedInputStream(new FileInputStream(file), 10240);
// Init servlet response.
response.reset();
// lire un fichier pdf
response.setHeader("Content-type", "application/pdf");
response.setContentLength((int)file.length());
response.setHeader("Content-disposition", "attachment; filename=" + node.getNomRepertoire());
response.setHeader("pragma", "public");
output = new BufferedOutputStream(response.getOutputStream(), 10240);
// Write file contents to response.
byte[] buffer = new byte[10240];
int length;
while ((length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
// Finalize task.
output.flush();
} finally {
// Gently close streams.
output.close();
input.close();
}
}
The problem is when I use this method it only downloads the file. For your information, I'm following this post: http://balusc.omnifaces.org/2006/05/pdf-handling.html
You should change
response.setHeader("Content-disposition", "attachment; filename=" + node.getNomRepertoire());
into
response.setHeader("Content-disposition", "inline; filename=" + node.getNomRepertoire());
So, use inline instead of attachment.
See also:
How to force files to open in browser instead of download (pdf)?

Downloading a file using JSF

Hi I am trying to download a file from server but at the end of my process I end up with only numbers and some weird characters on my browser. It's not downloading the file. I am using seam and JSF 1.2.
Here is my code:
public void writeBytesToResponse(UploadDefinition _instance, String path) {
FacesContext context = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) context .getExternalContext().getResponse();
try {
byte[] bytes = getFile(path);
response.reset();
response.setContentType(ContentType.PDF.getLabel());
response.setContentLength(bytes.length);
response.setHeader("Content-disposition", "attachment; filename=\"" + _instance.getFileName() + "\"");
OutputStream outputStream = response.getOutputStream();
outputStream.write(bytes);
outputStream.flush();
outputStream.close();
context.responseComplete();
} catch (Exception ex) {
ex.printStackTrace();
}
}
#SuppressWarnings("resource")
public byte[] getFile(String filePath) throws FileNotFoundException, IOException {
File file = new File(filePath);
InputStream is = new FileInputStream(file);
long length = file.length();
if (length > Integer.MAX_VALUE) {
throw new IOException("File is too large " + file.getName());
}
byte[] bytes = new byte[(int) length];
int offset = 0;
int numRead = 0;
while (offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
offset += numRead;
}
if (offset < bytes.length) {
throw new IOException("Could not completely read file " + file.getName());
}
is.close();
return bytes;
}
Here I call the method:
public void downloadFile() {
writeBytesToResponse(ud, path);
}
I got the answer, I was using <a4j:commandButton> on jsf and I changed it to <h:commandButton> then it worked. The point is not to use ajax.

Unable to download the created zipped file correctly from server

I am having a folder, I am trying to zip it and than on a button click event it should be downloaded on the user's machine. I am able to generate the zip file correctly. I have written the code to download it also but after it is getting downloaded to the user's machine from the server. It shows unable to open zip file as it is invalid.
How is this caused and how can I solve it? Here's the code which performs the download functionality.
public String getAsZip() {
try {
FacesContext ctx = FacesContext.getCurrentInstance();
ExternalContext etx = ctx.getExternalContext();
HttpServletResponse response = (HttpServletResponse) etx
.getResponse();
ServletOutputStream zipFileOutputStream = response
.getOutputStream();
response.setContentType("application/octet-stream");
response.setHeader(
"Content-Disposition",
"attachment; filename=" + downloadLink.substring(downloadLink.lastIndexOf("\\") + 1,downloadLink.length()));
response.setHeader("Cache-Control", "no-cache");
File zipFile = new File(downloadLink);
FileInputStream stream = new FileInputStream(zipFile);
response.setContentLength(stream.available());
int length = 0;
byte[] bbuf = new byte[response.getBufferSize()];
BufferedInputStream in = new BufferedInputStream(stream);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ((length = in.read(bbuf)) > 0) {
baos.write(bbuf, 0, length);
}
zipFileOutputStream.write(baos.toByteArray());
zipFileOutputStream.flush();
zipFileOutputStream.close();
response.flushBuffer();
in.close();
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
return "successZip";
}
See JSF 2.0 RenderResponse and ResponseComplete
The problem is that you do not call FacesContext#responseComplete(). That's why JSF will still render the view after you attached the download and append that to the response. This will cause the zipfile to be broken.

Resources